import os
import hublib.ui as ui
import ipywidgets as w
from IPython.display import display
import config

import eppy_funcs as ef
import sampling

from functools import partial


class FileManager:
    def __init__(self, extensions, dir=config.inDir, defaults=config.files, **kwargs):
        self.files = {}  # maps extension name to (current, {candidates}) tuples
        # defaults must already be in the directory
        for ext, file in defaults.items():
            if ext not in extensions:
                raise ValueError('{} is not a valid extension'.format(ext))
            self.files[ext] = (file, {file})
        self.directory = dir
        self.extensions = extensions
        self.out = w.Output()
        self.displayOptions()

        widgetDefaults = {'name': "Files", 'desc': '',
                          'maxsize': '10M', 'width': '30%', 'maxnum': 5}
        widgetDefaults.update(kwargs)

        multiLoader = ui.FileUpload(dir=dir, cb=self, **widgetDefaults)
        self.w = w.VBox([multiLoader.w, self.out])

    def __call__(self, w, fileNames):
        self.out.clear_output()
        badFiles = []
        with self.out:
            for name in fileNames:
                ext = name.split('.')[-1]
                name = self._short(name)
                if ext in self.extensions:
                    current, options = self.files.get(ext, ('File Needed', set()))
                    self.files[ext] = (name, options | {name})
                else:
                    badFiles.append(name)
            if badFiles:
                print(' and '.join([', '.join(badFiles[:-1]), badFiles[-1]]),
                      'are invalid files. Only files with the extensions',
                      ' or '.join([', '.join(self.extensions[:-1]), self.extensions[-1]]),
                      'are allowed')
        self.displayOptions()
        w.reset()

    def displayOptions(self):
        with self.out:
            for ext in self.extensions:
                current, options = self.files.get(ext, ('File Needed', ['File Needed']))
                dd = ui.Dropdown(name=ext + ' file', description='',
                                 value=current,
                                 options=options, cb=partial(self._setFile, ext=ext))
                display(dd)

    def _short(self, name):
        return name[len(self.directory) + 1:]

    def getFile(self, ext):
        # deliberetly does not catch key errors
        # might want to replace with __getitem__
        return os.path.join(self.directory, self.files[ext][0])

    def _setFile(self, w, file, ext):
        current, options = self.files[ext]
        self.files[ext] = (file, options)


fileTypes = ['building', 'idd', 'epw']
fm = FileManager(fileTypes)


def output(transformers):
    idf = None
    results = w.Output()

    def _getSamples(w):
        nonlocal idf
        global df
        if idf is None:
            idf = ef.get_idf(fm.getFile('building'), fm.getFile('idd'), fm.getFile('epw'))
        with results:
            print('Simulating...')
            df = sampling.dist_sampler(samplerType.value, transformers, samplesBox.value)
            df['energy use'] = ef.Evaluator(transformers, idf).df_apply(df)
            print('Done')

            display(df)
    goButton = w.Button(description='Get Samples')
    goButton.on_click(_getSamples)
    return w.VBox([goButton, results])


startButtons = w.HBox([ui.HideCodeButton().w, ui.RunAllButton().w])

samplerType = ui.Dropdown('Sampling method', '',
                          options={'Latin Hypercube': sampling.lhs,
                                   'Random': sampling.random,
                                   'LHS with minimax criterion': sampling.lhs_maximin,
                                   'Random, seeded': sampling.seeded_sampler},
                          value=sampling.lhs)

samplesBox = ui.Integer('Samples', value=5, min=1, max=20)

interface = w.VBox([fm.w, samplerType.w, samplesBox.w])
