#!/usr/bin/env python

import argparse
import configparser
import datetime
import logging
import os
import sys
from logging.handlers import RotatingFileHandler
from pathlib import Path

from stravalib import unithelper
from stravalib.client import Client

DEBUG = 0
LOG = 'get_activities'


class Config():
    def __init__(self, filename):
        self.config = configparser.ConfigParser()

        self.my_file = Path(filename)
        logger = logging.getLogger(LOG)
        if DEBUG > 0:
            logger.debug('[Config::init]: filename = %s', filename)
        if not self.my_file.is_file():
            if DEBUG > 0:
                logger.critical('[Config::init]: filename not found')
            print(-1)
            sys.exit(1)
        self.config.read(filenames=self.my_file)

    def get_str(self, section, option, default):
        """Get string option"""
        logger = logging.getLogger(LOG)
        try:
            return self.config[section].get(option, default)
        except:
            if DEBUG > 0:
                logger.critical(
                    '[Config::get_str]: Failed to get option: "%s", section: "%s"',
                    option,
                    section,
                    exc_info=True)
            return default

    def set_str(self, section, option, value):
        """Set value of section"""
        logger = logging.getLogger(LOG)
        try:
            self.config[section][option] = value
            with open(self.my_file, 'w') as configfile:
                self.config.write(configfile)
        except:
            if DEBUG > 0:
                logger.critical(
                    '[Config::set_str]: Failed to set option: "%s", section: "%s"',
                    option,
                    section,
                    exc_info=True)
            return


class Parser():
    def __init__(self):
        self.parser = argparse.ArgumentParser(description='Get strava info')
        self.parser.add_argument(
            'config',
            default='config.ini',
            help='path to the configuration file')
        self.parser.add_argument(
            '--debug', '-d', type=int, default=0, help='create debug file')
        self.args = self.parser.parse_args()


class Strava():
    def __init__(self, token, client_id, client_secret, year, config):
        logger = logging.getLogger(LOG)
        if DEBUG > 0:
            logger.debug('token: "%s", year: "%s"', token, year)
        self.current_year = datetime.date.today().year
        self.config = config
        if not year or year == 'current':
            year = self.current_year
        try:
            client = Client()
            # Exchange refresh token for a "new" access token.
            # If access_token has not expired (it expires every 6 hours)
            # You will get the same old token. Otherwise, you will get a new
            # token. which you have to save (update_token_information)
            # Read here: https://developers.strava.com/docs/authentication/
            # Specifically the "Refresh expired access tokens part"
            access_token = client.refresh_access_token(client_id,
                                                       client_secret, token)
            client.access_token = access_token["access_token"]
            self.activities = client.get_activities(
                after='{}-01-01T00:00:00Z'.format(str(year)),
                before='{}-01-01T00:00:00Z'.format(str(year + 1)),
                limit=500)
            if token != access_token["refresh_token"]:
                if DEBUG > 0:
                    logger.debug('There is a new token in town!!!')
                    logger.debug('old token: "%s". new token: "%s"', token,
                                 access_token["refresh_token"])
                self.update_token_information(access_token)
        except:
            if DEBUG > 0:
                logger.critical('failed to get activities', exc_info=True)
            print(-3)
            sys.exit(3)

    def update_token_information(self, token):
        """Write the newly recently obtained information"""
        self.config.set_str('Token', 'access_token', token['access_token'])
        self.config.set_str('Token', 'refresh_token', token['refresh_token'])
        self.config.set_str('Token', 'expires_at', str(token['expires_at']))

    def get_num_activities(self):
        return str(len(list(self.activities)))

    def get_total_time(self):
        """Get time for all activities"""
        elapse_time = 0
        for activity in self.activities:
            elapse_time += activity.elapsed_time.seconds
        t = str(datetime.timedelta(seconds=elapse_time))
        return t[:-3]

    def get_total_distance(self):
        """Get total distance in miles for all activities"""
        d = 0.0
        for activity in self.activities:
            d += float(activity.distance)

        return str(round(d * 0.0006213712, 1))

    def sortby(self, item):
        return item.start_date

    def get_last_bike_avg_speed(self):
        """Get the avg speed in miles per hour of the last bike ride"""
        """Types seem to be 'Run', 'Swim', 'Ride'"""
        logger = logging.getLogger(LOG)
        avg = 0.0
        for activity in sorted(self.activities, key=self.sortby, reverse=True):
            if DEBUG > 0:
                logger.debug('[get_last_bike_avg_speed]: type = "%s"',
                             str(activity.type))
            if activity.type == 'Ride':
                avg = unithelper.miles_per_hour(activity.average_speed)
                break

        return str(avg)


def set_logger():
    """Setups the logger"""
    logger = logging.getLogger(LOG)
    handler = RotatingFileHandler(
        '/tmp/' + LOG + '.log', maxBytes=10**6, backupCount=5)
    formatter = logging.Formatter('%(asctime)s_%(levelname)s: %(message)s')

    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)


if __name__ == '__main__':
    parser = Parser()
    DEBUG = int(parser.args.debug)
    set_logger()
    logger = logging.getLogger(LOG)
    config = Config(parser.args.config)
    token = config.get_str('Token', 'refresh_token', "")
    client_id = config.get_str('ApiInfo', 'client_id', "")
    client_secret = config.get_str('ApiInfo', 'client_secret', "")
    if not token or not client_id or not client_secret:
        if DEBUG > 0:
            logger.critical(
                'failed to get tokens. token: "%s", client_id: "%s", client_secret: "%s"',
                token, client_id, client_secret)
        print(-2)
        sys.exit(2)
    year = config.get_str('Workout', 'year', "")
    strava = Strava(token, client_id, client_secret, year, config)
    num_workouts = strava.get_num_activities()
    num_hours = strava.get_total_time()
    num_miles = strava.get_total_distance()
    avg_bike_speed = strava.get_last_bike_avg_speed()[:-7]
    print(num_workouts + ' ' + num_hours + ' ' + num_miles + 'm ' +
          avg_bike_speed + ' m/h')
