import time

import requests

from israelrailapi.train_station import station_name_to_id

# API key bundled in main.js of rail.co.il
API_KEY = "5e64d66cf03f4547bcac5de2de06b566"

USER_AGENT = (
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 "
    "Safari/605.1.15"
)
API_BASE = "https://rail-api.rail.co.il/rjpa/api/v1"
DEFAULT_HEADERS = {
    "User-Agent": USER_AGENT,
    "ocp-apim-subscription-key": API_KEY,
    "Content-Type": "application/json",
}


class TrainRoutePart(object):
    def __init__(self, data):
        self.data = data

        self.src = data['orignStation']
        self.dst = data['destinationStation']
        self.arrival = data['arrivalTime']
        self.departure = data['departureTime']
        self.platform = data['originPlatform']
        self.dst_platform = data['destPlatform']
        self.departure_delay = next(
            (e['difMin'] for e in data.get('etaDiffTimes', []) if e['stationId'] == self.src),
            0,
        )

    @staticmethod
    def parse_time(t):
        return time.strptime(t, "%d/%m/%Y %H:%M:%S")

    def __repr__(self):
        return "%s (%s) to %s (%s)" % (
            station_name_to_id(self.src), self.departure, station_name_to_id(self.dst), self.arrival)


class TrainRoute(object):
    def __init__(self, data):
        self.trains = self.parse(data)

        self.start_time = self.trains[0].departure
        self.end_time = self.trains[-1].arrival

    @staticmethod
    def parse(data):
        result = []
        for t in data:
            result.append(TrainRoutePart(t))
        return result

    def __repr__(self):
        return "%d trains in route, starting %s, arriving %s: %s\n" % (len(self.trains),
                                                                       self.start_time,
                                                                       self.end_time,
                                                                       self.trains)


class IsraelRailApi(object):
    def __init__(self, url, params, headers=None):
        self.arguments = None
        if headers is None:
            headers = DEFAULT_HEADERS
        self.url = '/'.join((API_BASE, url))
        self.params = params
        self.headers = headers

    def prepare_arguments(self, arguments):
        unknown_args = arguments.keys() - self.params.keys()
        if len(unknown_args) > 0:
            raise KeyError('Unknown arguments %s' % (unknown_args,))

        for k in self.params:
            if k not in arguments:
                if 'default' in self.params[k]:
                    arguments[k] = self.params[k]['default']
                elif self.params[k]['required'] is not False:
                    raise KeyError('Required argument %s not provided' % (k,))

        return arguments

    def parse(self, result):
        return result

    def request(self, **kwargs):
        self.arguments = self.prepare_arguments(kwargs)
        return self.parse(
            requests.post(self.url, json=self.arguments, headers=self.headers)
        )


class GetRoutesApi(IsraelRailApi):
    def __init__(self):
        super().__init__(
            "timetable/searchTrain",
            {
                "fromStation": {},
                "toStation": {},
                "date": {},
                "hour": {"default": "09:00"},
                "scheduleType": {"default": "ByDeparture"},
                "systemType": {"default": "2"},
                "languageId": {"default": "English"},
            },
        )

    def parse(self, raw_result):
        raw_result.raise_for_status()
        result = raw_result.json()['result']
        size = result['numOfResultsToShow']
        index = result['startFromIndex']

        routes = result['travels'][index: index + size]
        return [TrainRoute(r['trains']) for r in routes]
