from .exceptions import ValidationError
from .location import location_to_params
from .options import ForecastOptions, validate_days, validate_lang, validate_units
from .transport import HttpTransport


class BaseClient(object):
    def __init__(self,
                 token,
                 transport=None,
                 base_url=None,
                 timeout=None,
                 retries=None,
                 backoff_factor=None,
                 user_agent=None,
                 proxies=None,
                 verify_ssl=True,
                 session=None,
                 auth_in_query=False,
                 retry_on_429=True,
                 default_units=None,
                 default_lang=None):
        if not token or not isinstance(token, str):
            raise ValidationError("token must be a non-empty string")
        self._token = token
        self._auth_in_query = auth_in_query
        self._default_units = default_units
        self._default_lang = default_lang

        if transport is not None:
            self._transport = transport
        else:
            kwargs = {
                "base_url": base_url,
                "timeout": timeout,
                "retries": retries,
                "backoff_factor": backoff_factor,
                "user_agent": user_agent,
                "proxies": proxies,
                "verify_ssl": verify_ssl,
                "session": session,
                "retry_on_429": retry_on_429,
            }
            cleaned = {}
            for key in kwargs:
                if kwargs[key] is not None:
                    cleaned[key] = kwargs[key]
            self._transport = HttpTransport(**cleaned)

    def _with_auth(self, params):
        headers = {}
        if self._auth_in_query:
            params["key"] = self._token
        else:
            headers["X-token"] = self._token
        return params, headers

    def _build_params(self,
                      location,
                      options,
                      default_days=None,
                      supports_days=True,
                      supports_units=True,
                      supports_lang=True):
        params = location_to_params(location)
        if options is None:
            options = ForecastOptions()
        if not isinstance(options, ForecastOptions):
            raise ValidationError("options must be ForecastOptions or None")

        if supports_days:
            days = options.days
            if days is None:
                days = default_days
            validate_days(days)
            if days is not None:
                params["days"] = int(days)

        if supports_units:
            units = options.units
            if units is None:
                units = self._default_units
            validate_units(units)
            if units is not None:
                params["unit"] = units

        if supports_lang:
            lang = options.lang
            if lang is None:
                lang = self._default_lang
            validate_lang(lang)
            if lang is not None:
                params["lang"] = lang

        return params
