#!/usr/bin/python
# -*- coding: utf8 -*-
# -*- Mode: Python; py-indent-offset: 4 -*-
# pylint: disable=C0103
"""
    Main file of timevortex.currencost project.
"""

from __future__ import print_function
import logging
import logging.config
from currentcost.utils import argument_parser, init_message, verbose_mode
from currentcost.utils import data_validator, LOG_FILE_ERROR
from messager.utils import ERROR, TTY_DISCONNECTED, TTY_CONNECTION_PROBLEM
from messager.utils import TTY_CONNECTION_SUCCESS, TIMESERIES
from time import sleep
from messager.rbmq_messager import RabbitMQMessager
from filestorage.config import Config
import serial
import ConfigParser
import os
from currentcost.utils import ACCESS_RIGHT_ERROR, get_currentcost_message
from datetime import datetime
import json
from time import tzname

# Globals for this file
DEFAULT_CONFIG_FILE = "/opt/timevortex/config.ini"
BAUDS = 57600
# Initialize logger
LOGGER = logging.getLogger("currentcost")

MISSING_VARIABLE_ID = "Missing variable_id parameter. Process terminated."
MISSING_SITE_ID = "Missing site_id parameter. Process terminated."
MISSING_LOG_FILE = "Missing logging file configuration. Process terminated."
MISSING_DATA_FOLDER = "Missing data folder path. Process terminated."
MISSING_TTY_PORT = "Missing tty_port parameter. Process terminated."
MISSING_TIMEOUT = "Missing timeout parameter. Process terminated."
MISSING_USB_RETRY = "Missing usb_retry parameter. Process terminated."


def main():
    """
        Main function of this module.
    """
    # Parse command line argument and format it into according variable
    args = argument_parser()

    config_file = args.config_file
    if config_file is None:
        config_file = DEFAULT_CONFIG_FILE
    config = Config(config_file)
    verbose = args.verbose

    variable_id = config.get_currentcost_variable_id()
    site_id = config.get_currentcost_site_id()
    rabbitmq_username = config.get_messager_rabbitmq_username()
    rabbitmq_password = config.get_messager_rabbitmq_password()
    rabbitmq_host = config.get_messager_rabbitmq_host()
    log_conf = config.get_currentcost_log_file()
    timeseries_args = {
        "ch1_w": config.get_currentcost_ch1_w(),
        "ch2_w": config.get_currentcost_ch2_w(),
        "ch3_w": config.get_currentcost_ch3_w(),
        "tmpr": config.get_currentcost_tmpr(),
    }
    data_folder = config.get_filestorage_data_folder()
    tty_port = config.get_currentcost_tty_port()
    timeout = config.get_currentcost_timeout()
    usb_retry = config.get_currentcost_usb_retry()

    # Print and exit if problem with parameter
    if variable_id is None:
        print(MISSING_VARIABLE_ID)
        return
    if site_id is None:
        print(MISSING_SITE_ID)
        return
    if log_conf is None:
        print(MISSING_LOG_FILE)
        return
    if data_folder is None:
        print(MISSING_DATA_FOLDER)
        return
    if tty_port is None:
        print(MISSING_TTY_PORT)
        return
    if timeout is None:
        print(MISSING_TIMEOUT)
        return
    if usb_retry is None:
        print(MISSING_USB_RETRY)
        return

    # Init logging file
    try:
        logging.config.fileConfig(log_conf)
    except ConfigParser.NoSectionError:
        print(LOG_FILE_ERROR % (log_conf))
        return
    except IOError:
        print(ACCESS_RIGHT_ERROR % (log_conf))
        return
    # Active verbose mode
    verbose_mode(verbose)
    # Initialize ser_connection
    ser_connection = None
    # Try write file in data_folder
    try:
        if not os.path.exists(data_folder):
            os.makedirs(data_folder)
        test_filename = "%s/test.ini" % data_folder
        test_data_folder = open(test_filename, "w")
        test_data_folder.write("Writing test in a test file\n")
        test_data_folder.close()
        os.remove(test_filename)
    except IOError:
        print(ACCESS_RIGHT_ERROR % (data_folder))
        return
    except OSError:
        print(ACCESS_RIGHT_ERROR % (data_folder))
        return

    # Init log message
    init_message(variable_id, site_id, tty_port, log_conf)
    # Initialize messager
    messager = RabbitMQMessager(
        rabbitmq_username,
        rabbitmq_password,
        rabbitmq_host)
    # Start the main loop
    while True:
        try:
            # If we are not connected to TTY ort
            if ser_connection is None:
                try:
                    # We create a tty connection
                    ser_connection = serial.Serial(
                        tty_port,
                        BAUDS,
                        timeout=timeout)
                except (OSError, serial.serialutil.SerialException):
                    # If tty not exist we send according error an retry in
                    # a moment
                    message = {
                        "siteID": site_id,
                        "variableID": variable_id,
                        "value": TTY_CONNECTION_PROBLEM % (
                            variable_id,
                            site_id,
                            tty_port),
                        "date": datetime.utcnow().isoformat('T'),
                        "dstTimezone": tzname[1],
                        "nonDstTimezone": tzname[0]
                    }
                    messager.send(
                        ERROR,
                        json.dumps(message))
                    sleep(usb_retry)
                # When we are connected, we log this success
                else:
                    error = TTY_CONNECTION_SUCCESS % (
                        variable_id,
                        site_id,
                        tty_port)
                    LOGGER.info(error)
            # If we are connected to TTY port
            if ser_connection is not None:
                # We wait for a new message on this socket
                data = ser_connection.readline()
                data_date = datetime.utcnow().isoformat('T')
                data_dst_timezone = tzname[1]
                data_non_dst_timezone = tzname[0]
                # We parse the result
                topic, message = data_validator(data, variable_id, site_id)
                message = {
                    "siteID": site_id,
                    "variableID": variable_id,
                    "value": message,
                    "date": data_date,
                    "dstTimezone": data_dst_timezone,
                    "nonDstTimezone": data_non_dst_timezone
                }

                topic, message, series = get_currentcost_message(
                    topic, message, data, timeseries_args, data_folder)

                # We send message
                messager.send(topic, message)

                for serie in series:
                    # We send JSON series
                    messager.send(
                        TIMESERIES,
                        json.dumps(serie))
        # If during this process, someone deactivate USB connection
        except serial.serialutil.SerialException:
            # We reinit serial connection
            if ser_connection is not None:
                ser_connection.close()
                ser_connection = None
            # And we log this error
            error = TTY_DISCONNECTED % (
                variable_id,
                site_id,
                tty_port)
            LOGGER.info(error)


if __name__ == "__main__":
    # Launch main method
    main()
