import os
import pathlib
from typing import Union, List
from fastapi import FastAPI

__author__ = "Tiago Prata"
__copyright__ = "Copyright 2022, ABB Automacao Ltda (Brazil)"
__credits__ = ["ABB Automacao Ltda", "Tiago Prata"]
__license__ = "Copyright"
__version__ = "1.0.0"
__maintainer__ = "AssetVista Team"
__email__ = "BR-assetvista@abb.com"
__status__ = "Development (do not use in production)"

# TODO: Add comments to classes and functions
# TODO: Create test script
# TODO: Replace prints by logs

AMS_FOLDER_NAME = 'assetmonitors'
REQUIRED_FILES_IN_AM_FOLDER = ['_am_def.py', '_cond_def.py', 'router.py']


def _is_valid_am_folder(folder: Union[str, pathlib.Path]):
    ''' Verify if the AM folder contains the minimum files requirements to be an Asset Monitor folder
    '''
    required_files = REQUIRED_FILES_IN_AM_FOLDER.copy()

    if not folder.is_dir(): print(''.join(['Asset Monitor path (', folder.name, ') is not a folder'])); return False

    for subitem in os.listdir(folder):
        if os.path.isfile(os.path.join(folder, subitem)):
            if subitem in required_files:
                required_files.remove(subitem)
                print(''.join(['Requirement ', subitem, ' found on Asset Monitor folder']))

    if len(required_files) == 0:
        print(''.join(['All required files found on ', folder.name]))
        return True
    else:
        print(''.join(['Missing required files on folder ', folder.name]))
        print('Missing files:')
        print(required_files)
        return False



def _get_ams_list(assetmonitors_folder_path, folders_to_be_ignored = []):
    subfolders = []
    for folder in os.scandir(assetmonitors_folder_path):
        if not folder.is_dir(): print(''.join(['Asset Monitor path (', folder.name, ') is not a folder'])); continue
        if folder.name in folders_to_be_ignored: print(''.join(['Folder ', folder.name, ' marked to be ignored.'])); continue
        if folder.name.startswith('__'): print(''.join(['Folder ', folder.name, ' ignored because it starts with dunder (__)'])); continue
        if folder.name.startswith('.'): print(''.join(['Folder ', folder.name, ' ignored because it starts with dor (.)'])); continue
        if not _is_valid_am_folder(folder): print('Invalid AM folder!')

        subfolders.append(folder.name)

    return subfolders


def _include_am_routers(fastapi_app: FastAPI, ams_list):

    # Importing AMs libs
    for am in ams_list:
        import_str = ''.join(['from ', AMS_FOLDER_NAME, '.', am, ' import router as ', am])
        print(''.join(['Importing: ', import_str]))
        exec(import_str)

    # Including routers
    for am in ams_list:
        router = eval(''.join([am, '.router']))
        fastapi_app.include_router(router)

    return fastapi_app


def add_assetvista_routes(fastapi_app: FastAPI, assetmonitors_folder_path, folders_to_be_ignored = []):
    ams_list = _get_ams_list(assetmonitors_folder_path, folders_to_be_ignored)
    return _include_am_routers(fastapi_app, ams_list)


def create_route_example(avtype_numerics: List[str] = None,
                        avtype_integers: List[str] = None,
                        avtype_strings: List[str] = None,
                        avtype_booleans: List[str] = None,
                        numerics: List[str] = None,
                        integers: List[str] = None,
                        strings: List[str] = None,
                        booleans: List[str] = None):

    route_example = {}

    # TODO: Get examples from the avtypes instead of typing each example.

    if avtype_numerics != None:
        for avtype_numeric in avtype_numerics:
            route_example[avtype_numeric] = {'value':
                                                '{"description": "", "value": 40.0, "unit": "", "in_use": true, "timestamp": "2022-05-03T05:24:38.712Z", "simulation_enabled": false, "simulation_value": 200.0, "max": 13.0, "min": 16.0, "out_of_range": false, "quality": 1024, "dataType": "AvtypeNumeric"}',
                                            'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'String'}

    if avtype_integers != None:
        for avtype_integer in avtype_integers:
            route_example[avtype_integer] = {'value':
                                                '{"description": "", "value": 40, "unit": "", "in_use": true, "timestamp": "2022-05-03T05:24:38.712Z", "simulation_enabled": false, "simulation_value": 200, "max": 13, "min": 16, "out_of_range": false, "quality": 1024, "dataType": "AvtypeInteger"}',
                                            'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'String'}

    if avtype_strings != None:
        for avtype_string in avtype_strings:
            route_example[avtype_string] = {'value':
                                                '{"description": "", "value": "test", "in_use": true, "timestamp": "2022-05-03T05:24:38.712Z", "simulation_enabled": false, "simulation_value": "sim value", "quality": 1024, "dataType": "AvtypeString"}',
                                            'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'String'}

    if avtype_booleans != None:
        for avtype_boolean in avtype_booleans:
            route_example[avtype_boolean] = {'value':
                                                '{"description": "", "value": true, "in_use": true, "timestamp": "2022-05-03T05:24:38.712Z", "simulation_enabled": false, "simulation_value": false, "quality": 1024, "dataType": "AvtypeBoolean"}',
                                            'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'String'}

    if numerics != None:
        for numeric in numerics:
            route_example[numeric] = {'value':
                                        40.0,
                                    'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'Numeric'}

    if integers != None:
        for integer in integers:
            route_example[integer] = {'value':
                                        40,
                                    'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'Integer'}

    if strings != None:
        for string in strings:
            route_example[string] = {'value':
                                        'test',
                                    'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'String'}

    if booleans != None:
        for boolean in booleans:
            route_example[boolean] = {'value':
                                        True,
                                    'quality': 1024, 'timestamp': '2021-04-09T16:48:23.3Z', 'dataType': 'Boolean'}

    route_example["previousAlarms"] = {}


    return route_example