# -*- coding: utf-8 -*-
"""
    wakatime
    ~~~~~~~~

    Event appender for Wakati.Me, a time tracking api for programmers.

    :copyright: (c) 2013 Alan Hamlett.
    :license: BSD, see LICENSE for more details.
"""

from __future__ import print_function

__title__ = 'wakatime'
__version__ = '0.0.1'
__author__ = 'Alan Hamlett'
__license__ = 'BSD'
__copyright__ = 'Copyright 2013 Alan Hamlett'


# allow running script directly
if __name__ == '__main__' and __package__ is None:
    import os, sys
    parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.insert(0, parent_dir)
    import wakatime
    __package__ = 'wakatime'
    del os, sys


import base64
import json
import logging
import os
import platform
import re
import sys
import time
import traceback
import urllib2

from .log import setup_logging
from .project import find_project

try:
    import argparse
except ImportError:
    from .packages import argparse


log = logging.getLogger(__name__)


class FileAction(argparse.Action):

    def __call__(self, parser, namespace, values, option_string=None):
        values = os.path.realpath(values)
        setattr(namespace, self.dest, values)


def parseArguments():
    parser = argparse.ArgumentParser(
            description='Wakati.Me event api appender')
    parser.add_argument('--file', dest='targetFile', metavar='file',
            action=FileAction, required=True,
            help='absolute path to file for current event')
    parser.add_argument('--time', dest='timestamp', metavar='time',
            type=float,
            help='optional floating-point unix epoch timestamp; '+
                'uses current time by default')
    parser.add_argument('--endtime', dest='endtime',
            help='optional end timestamp turning this event into '+
                'a duration; if a non-duration event occurs within a '+
                'duration, the duration is ignored')
    parser.add_argument('--write', dest='isWrite',
            action='store_true',
            help='note event was triggered from writing to a file')
    parser.add_argument('--plugin', dest='plugin',
            help='optional text editor plugin name and version '+
                'for User-Agent header')
    parser.add_argument('--key', dest='key',
            help='your wakati.me api key; uses api_key from '+
                '~/.wakatime.conf by default')
    parser.add_argument('--logfile', dest='logfile',
            help='defaults to ~/.wakatime.log')
    parser.add_argument('--config', dest='config',
            help='defaults to ~/.wakatime.conf')
    parser.add_argument('--verbose', dest='verbose', action='store_true',
            help='turns on debug messages in log file')
    parser.add_argument('--version', action='version', version=__version__)
    args = parser.parse_args()
    if not args.timestamp:
        args.timestamp = time.time()
    if not args.key:
        default_key = get_api_key(args.config)
        if default_key:
            args.key = default_key
        else:
            parser.error('Missing api key')
    return args


def get_api_key(configFile):
    if not configFile:
        configFile = '~/.wakatime.conf'
    api_key = None
    try:
        cf = open(os.path.expanduser('~/.wakatime'))
        for line in cf:
            line = line.split('=', 1)
            if line[0] == 'api_key':
                api_key = line[1].strip()
        cf.close()
    except IOError:
        log.error('Could not read from config file.')
    return api_key


def get_user_agent(plugin):
    user_agent = 'wakatime/%s %s' % (__version__, platform.platform())
    if plugin:
        user_agent = plugin+' '+user_agent
    return user_agent


def send_action(project_name=None, tags=None, key=None, targetFile=None,
        timestamp=None, endtime=None, isWrite=None, plugin=None, **kwargs):
    url = 'https://www.wakati.me/api/v1/events'
    log.debug('Sending event to api at %s' % url)
    data = {
        'timestamp': timestamp,
        'file': targetFile,
    }
    if endtime:
        data['endtime'] = endtime
    if isWrite:
        data['isWrite'] = isWrite
    if project_name:
        data['project'] = project_name
    if tags:
        data['tags'] = tags
    log.debug(data)
    request = urllib2.Request(url=url, data=json.dumps(data))
    user_agent = get_user_agent(plugin)
    request.add_header('User-Agent', user_agent)
    request.add_header('Content-Type', 'application/json')
    request.add_header('Authorization', 'Basic %s' % base64.b64encode(key))
    response = None
    try:
        response = urllib2.urlopen(request)
    except urllib2.HTTPError as exc:
        data = {
            'response_code': exc.getcode(),
            'response_content': exc.read(),
            sys.exc_info()[0].__name__: str(sys.exc_info()[1]),
        }
        if log.isEnabledFor(logging.DEBUG):
            data['traceback'] = traceback.format_exc()
        log.error(data)
    except:
        data = {
            sys.exc_info()[0].__name__: str(sys.exc_info()[1]),
        }
        if log.isEnabledFor(logging.DEBUG):
            data['traceback'] = traceback.format_exc()
        log.error(data)
    else:
        log.debug({
            'response_code': response.getcode(),
            'response_content': response.read(),
        })
        if response.getcode() >= 200 and response.getcode() < 300:
            return True
    return False


def main():
    args = parseArguments()
    setup_logging(args, __version__)
    if os.path.isfile(args.targetFile):
        project = find_project(args.targetFile)
        tags = project.tags()
        if send_action(project=project, tags=tags, **vars(args)):
            return 0
        return 102
    else:
        log.debug('File does not exist; ignoring this event.')
    return 101


if __name__ == '__main__':
    sys.exit(main())
