#!/usr/bin/env python2
#coding: utf-8

import os
import sys
import shelve
import socket
import codecs
import requests
import webbrowser
import ConfigParser

from __init__      import __version__
from urlparse      import urlparse
from argparse      import ArgumentParser
from BeautifulSoup import BeautifulSoup

env = os.environ
REGISTORY = os.path.join(env["HOME"], ".accounts")

HERE = os.path.abspath(os.path.dirname(__file__))
CONFIG_FILE = os.path.join(HERE, "services.ini")

def make_parser():
    parser = ArgumentParser(
                prog="accounts",
                version=__version__,
                description="The accounts saves your accounts of web services.")

    subparsers = parser.add_subparsers(
                            dest="command",
                            title="accounts positional arguments.")
    cmd_add = subparsers.add_parser(
                            "add",
                            help="accounts add account to registory.")
    cmd_add.add_argument(
                "service",
                help="any web service name, url, or domain." \
                     "When you set the URL to service, accounts " \
                     "set the service name to domain name.")
    cmd_add.add_argument(
                "account",
                help="your account name.")
    cmd_add.add_argument(
                "-U", "--url",
                help="If you set the not registrated service name, " \
                     "this --url argument can set URL.")



    cmd_upd = subparsers.add_parser(
                            "upd",
                            help="accounts updates the account name.")
    cmd_upd.add_argument(
                "service",
                help="your registrated service name.")
    cmd_upd.add_argument(
                "account",
                help="the account name what you want update")



    cmd_del = subparsers.add_parser(
                             "del",
                             help="accounts deletes the service account.")
    cmd_del.add_argument(
                "service",
                help="your registrated service name.")



    cmd_login = subparsers.add_parser(
                            "login",
                            help="accounts opens browser to login the service.")
    cmd_login.add_argument(
                "service",
                help="your registrated service name.")

    cmd_list = subparsers.add_parser(
                            "list",
                            help="accounts shows the list of accounts.")
    cmd_list.add_argument(
                "-S", "--service",
                action="store_true", dest="service",
                help="accounts shows list of the known services.")



    return parser

class ServiceError(BaseException):
    pass

def adjust_service(service):
    if any(map(s.startswith, ["http", "ftp"])):

        res = requests.get(service)
        if res.status_code == 200:
            # url
            parsed = urlparse(service)
            return parsed.netloc.split(".")[0]

        else:
            raise ServiceError("service (url) not found.")

    if service.find(".") == -1:
        # nomal
        return service

    else:
        try:
            host = socket.gethostbyname(service)
            # domain
            return service.split(".")[0]

        except socket.gaierror:
            raise ServiceError("service (domain) not found.")

def _get_config():

    config = ConfigParser.ConfigParser()

    with codecs.open(CONFIG_FILE, "r", encoding="utf-8") as f:
        config.readfp(f)

    return config

def get_service(service_name):

    config = _get_config()
    service_in_config = service_name.lower() in \
                            (s.lower() for s in config.sections())

    if service_in_config:
        name = config.get(service_name, "name")
        url = config.get(service_name, "url")
        login_url = config.get(service_name, "login_url")

    else:
        # Get information about service from Google...
        name, url, login_url = fetch_google(service_name)

        # ... and save it to the services.ini file
        config.add_section(service_name)
        config.set(service_name, "name", name)
        config.set(service_name, "login", url)
        config.set(service_name, "login_url", login_url)

        with codecs.open(CONFIG_FILE, "w", encoding="utf-8") as f:
            f.write(config)

    return (name.encode("utf-8"), url, login_url)


def fetch_google(service):

    url = "http://www.google.co.jp/search?hl=ja&num=1&q="

    res = requests.get(url + service)
    soup = BeautifulSoup(res.text)

    base = soup.findAll("h3", {"class":"r"})[0]
    name = base.text
    url = "http://" + base.a["href"][7:].split("/")[2]
    login_url = url+"/login"
    return (name, url, login_url)

def check_registory(registory):

    if not registory.has_key("accounts") or registory["accounts"] == []:
        print "you still don't save service."
        return False

    else:
        return True

def main():

    parser = make_parser()

    if len(sys.argv) == 1:
        parser.parse_args(["-h"])

    args = parser.parse_args()

    if args.command == "add":

        name, url, login_url = get_service(adjust_service(args.service))
        data = \
            {
                "service": name,
                "account": args.account,
                "url": url,
                "login_url": login_url,
            }

        registory = shelve.open(REGISTORY)

        if not registory.has_key("accounts"):
            registory["accounts"] = [data]

        else:
            d = registory["accounts"]
            d.append(data)
            registory["accounts"] = d

        registory.close()

        print "accounts saves the {service} account: {account}".format(data)
        return 0

    elif args.command == "list":

        if args.service:
            config = _get_config()
            print "services:"
            # Prints out a list of all services
            for service in config.sections():
                print "  - {}".format(service)

            return 0

        registory = shelve.open(REGISTORY)

        if not check_registory(registory):
            return 1

        print "accounts:"
        for data in registory["accounts"]:
            print "  - {}: {}".format(data["service"], data["account"])

        return 0

    elif args.command == "upd":

        registory = shelve.open(REGISTORY)
        data = registory["accounts"]

        for d in data:
            if args.service == d["service"]:
                index = data.index(d)

                original = d["account"]
                service = d["service"]
                url = d["url"]
                login_url = d["login_url"]

                data.pop(index)
                data.append({
                    "service": service,
                    "account": args.account,
                    "url":     url,
                    "login_url": login_url
                })

                registory["accounts"] = data
                registory.close()
                print "accounts updates the {} service: {} -> {}".format(d["service"], original, args.account)
                return 0

        raise ServiceError("service not found.")

    elif args.command == "del":

        registory = shelve.open(REGISTORY)
        data = registory["accounts"]

        for d in data:
            if args.service == d["service"]:
                index = data.index(d)
                data.pop(index)

                registory["accounts"] = data
                registory.close()
                print "accounts deletes the {} account.".format(args.service)
                return 0

        raise ServiceError("service not found.")

    elif args.command == "login":

        registory = shelve.open(REGISTORY)

        if not check_registory(registory):
            return 1

        data = registory["accounts"]

        for d in data:
            if args.service == d["service"]:
                login_url = d["login_url"]
                webbrowser.open(login_url)

if __name__ == "__main__":

    sys.exit(main())
