import configparser
import os

import pytz

from flask_monitoringdashboard.core.config.parser import parse_string, parse_version, parse_bool, parse_literal
from tzlocal import get_localzone


class Config(object):
    """
        The settings can be changed by setting up a config file. For an example of a config file, see
         config.cfg in the main-directory. 
    """

    def __init__(self):
        """
            Sets the default values for the project
        """
        # dashboard
        self.version = '1.0'
        self.link = 'dashboard'
        self.monitor_level = 3
        self.outlier_detection_constant = 2.5
        self.sampling_period = 0

        # database
        self.database_name = 'sqlite:///flask_monitoringdashboard.db'
        self.table_prefix = ''

        # authentication
        self.username = 'admin'
        self.password = 'admin'
        self.guest_username = 'guest'
        self.guest_password = ['guest_password']
        self.security_token = 'cc83733cb0af8b884ff6577086b87909'

        # visualization
        self.colors = {}
        self.timezone = pytz.timezone(str(get_localzone()))

        # define a custom function to retrieve the session_id or username
        self.group_by = None

    def init_from(self, file=None, envvar=None):
        """
            The config_file must at least contains the following variables in section 'dashboard':
            - APP_VERSION: the version of the app that you use. Updating the version helps in
                showing differences in execution times of a function over a period of time.
            - GIT = If you're using git, then it is easier to set the location to the .git-folder,
                The location is relative to the config-file.
            - CUSTOM_LINK: The dashboard can be visited at localhost:5000/{CUSTOM_LINK}.
            - MONITOR_LEVEL: The level for monitoring your endpoints. The default value is 3.
            - OUTLIER_DETECTION_CONSTANT: When the execution time is more than this constant *
                average, extra information is logged into the database. A default value for this
                variable is 2.5.
            - SAMPLING_PERIOD: Time between two profiler-samples. The time must be specified in ms.
                If this value is not set, the profiler continuously monitors.

            The config_file must at least contains the following variables in section 'authentication':
            - USERNAME: for logging into the dashboard, a username and password is required. The
                username can be set using this variable.
            - PASSWORD: same as for the username, but this is the password variable.
            - GUEST_USERNAME: A guest can only see the results, but cannot configure/download data.
            - GUEST_PASSWORD: A guest can only see the results, but cannot configure/download data.
            - SECURITY_TOKEN: Used for getting the data in /get_json_data

            The config_file must at least contains the following variables in section 'database':
            - DATABASE: Suppose you have multiple projects where you're working on and want to
                separate the results. Then you can specify different database_names, such that the
                result of each project is stored in its own database.
            - TABLE_PREFIX: A prefix to every table that the Flask-MonitoringDashboard uses, to ensure
                that there are no conflicts with the user of the dashboard.

            The config_file must at least contains the following variables in section 'visualization':
            - TIMEZONE: The timezone for converting a UTC timestamp to a local timestamp.
                for a list of all timezones, use the following:

                >>> import pytz  # pip install pytz
                >>> print(pytz.all_timezones)

            - COLORS: A dictionary to override the colors used per endpoint.

            :param file: a string pointing to the location of the config-file.
            :param envvar: a string specifying which environment variable holds the config file location
        """

        if envvar:
            file = os.getenv(envvar)
        if not file:
            # Travis does not need a config file.
            if '/home/travis/build/' in os.getcwd():
                return
            print("No configuration file specified. Please do so.")
            return

        parser = configparser.RawConfigParser()
        try:
            parser.read(file)

            # parse 'dashboard'
            self.version = parse_version(parser, 'dashboard', self.version)
            self.link = parse_string(parser, 'dashboard', 'CUSTOM_LINK', self.link)
            self.monitor_level = parse_literal(parser, 'dashboard', 'MONITOR_LEVEL', self.monitor_level)
            self.outlier_detection_constant = parse_literal(parser, 'dashboard', 'OUTlIER_DETECTION_CONSTANT',
                                                            self.outlier_detection_constant)
            self.sampling_period = parse_literal(parser, 'dashboard', 'SAMPLING_RATE', self.sampling_period) / 1000

            # parse 'authentication'
            self.username = parse_string(parser, 'authentication', 'USERNAME', self.username)
            self.password = parse_string(parser, 'authentication', 'PASSWORD', self.password)
            self.security_token = parse_string(parser, 'authentication', 'SECURITY_TOKEN', self.security_token)
            self.guest_username = parse_string(parser, 'authentication', 'GUEST_USERNAME', self.guest_username)
            self.guest_password = parse_literal(parser, 'authentication', 'GUEST_PASSWORD', self.guest_password)

            # database
            self.database_name = parse_string(parser, 'database', 'DATABASE', self.database_name)
            self.table_prefix = parse_string(parser, 'database', 'TABLE_PREFIX', self.table_prefix)

            # visualization
            self.colors = parse_literal(parser, 'visualization', 'COLORS', self.colors)
            self.timezone = pytz.timezone(parse_string(parser, 'visualization', 'TIMEZONE', self.timezone.zone))
        except configparser.Error:
            raise
