import numpy as np
import pandas as pd

class chart :
    @staticmethod
    def get(_data,_config) :
        # r = {}
        # for _key in _config :
        #     r[_key] = {'about':_config[_key]['about'],'chart':[]}
        #     _pointers = _config[_key]['apply']
        #     _pointers = [_pointers] if type(_pointers) == str else _pointers
        #     r[_key]['chart'] += [getattr(chart,_name)(_data,_config[_key]) for _name in _pointers if hasattr(chart,_name)]
        # return [r]
        r = {}
        for _key in _config :
            _options = _config[_key]['options']
            r[_key] = {'about':_config[_key]['about'],'css':_config[_key]['css'],'charts':[]}
            _charts = []
            for _itemOption in _options :
                _type = _itemOption['type']
                if hasattr(chart,_type) :
                    _pointer = getattr(chart,_type)

                    _chartOption = _pointer(_data,_itemOption)
                    _tag = 'options' if _type != 'scalar' else 'html'
                    if 'title' in _itemOption and _itemOption['type'] != 'scalar' :
                        _chartOption['title']  = {'text':_itemOption['title'],'align':'center'}
                        _chartOption['legend'] = {'position':'bottom','itemMargin':{'horizontal':4,'vertical':10}}
                        
                        _chartOption['chart']['height'] = 300
                        # _chartOption['chart']['height'] = '100%'
                        # _chartOption['responsive'] = [{'breakpoint':480,'options':{'chart':{'width':300}}}]
                    _charts.append ({"type":_type,_tag:_chartOption})
            if _charts :
                r[_key]['charts'] = _charts
                    
        #    for _pointer in _pointers :
            #    r[_key]['chart'].append(_pointer(_data,_config[_key]))
               
        #    _pointers = [getattr(chart,_name) for _name in _config[_key]['options']['apply'] if hasattr(chart,_name)]
        #    r[_key] = {'about':_config[_key]['about'],'chart':[]}
        #    for _pointer in _pointers :
        #        r[_key]['chart'].append(_pointer(_data,_config[_key]))
           

        return r
    @staticmethod
    def format_digit (value):
        if value > 1000000 :
            return np.divide(value,1000000).round(2).astype(str) + ' M'
        elif value > 1000 :
            return np.divide(value,1000).round(2).astype(str)+ ' K'
        return value
    @staticmethod
    def scalar(_data,_config) :
        """
        Only focusing on axis.y 
        """
        _columns = _config['axis']['y']
        if _data.shape[0] > 1 :
            _apply = 'sum' if 'apply' not in _config else _config['apply']
            # values = _data[_columns].sum().values.tolist()
            values = getattr(_data[_columns],_apply)().values.round(3).tolist()
        else:
            values = _data[_columns].values.tolist()[0]
        
        _html = [f'<div class="scalar"><div class="value">{chart.format_digit(values[_index])}</div><div class="label">{_columns[_index].replace("_"," ") }</div></div>' for _index in np.arange(len(values))]
        return ' '.join(_html)
    @staticmethod
    def donut(_data,_config):
        options = {"chart":{"type":"donut"}}
        _yaxis = _config['axis']['y']
        _apply = 'sum' if 'apply' not in _config else _config['apply']
        # options['series'] = _data[_yaxis].sum().values.tolist()
        options['series'] = getattr(_data[_yaxis],_apply)().values.round(3).tolist()
        options['labels'] = [_name.replace('_',' ').upper() for _name in _yaxis]
        options["dataLabels"]= {
          "enabled": False
        }
        return options  
    @staticmethod
    def column(_data,_config):
        if 'apply' in _config :
            _fn = _config['apply']
            _yaxis = _config['axis']['y']
            _values = getattr(_data[_yaxis],_fn)().values #.sum()
            _data =  (pd.DataFrame([dict(zip(_yaxis,_values))]))
            

        
        options = chart.barStacked(_data,_config)
        options['chart'] = {'type':'bar'}
        if 'title' in _config :
            options['title'] = {'text':_config['title'],'align':'center','style':{'text-transform':'upperCase','fontSize':'18px'}}
            pass
        
        options['stroke'] = {'show':True,'width':2,'colors':['transparent']}
        if _data.shape[0] == 1:
            options['xaxis']['categories'] = [_name.replace('_',' ').upper() for _name in _config['axis']['x']]
        # options['plotOptions'] = {'bar':{'columnWidth':'55%'}}
        return options
    @staticmethod
    def barStacked(_data,_config):
        options = {"series":[],  "chart": {
          "type": 'bar','stacked':True}
        }
        # options['plotOptions'] = {'bar':{'horizontal':True}}
        # options['legend'] = {'position':'bottom'} # {'position':'right','horizontalAlign':'left','offsetX':40}

        _xaxis = _data[_config['axis']['x']].values.tolist()        
        options["xaxis"]={"categories":_xaxis}
        for _col in _config['axis']['y'] :
            options['series'] += [{'name':_col.replace('_',' ').upper(), 'data':_data[_col].tolist()}]
        return options
    @staticmethod
    def radialBar (_data,_config) :
      
        _options = {
          "series": _config["axis"]["y"],
          "labels": _config["axis"]["x"],
          "chart": {
          "type": 'radialBar',
          "offsetY": -20,
          "sparkline": {
            "enabled": True
          }
        },
        # "plotOptions": {
        #   "radialBar": {
        #     "startAngle": -90,
        #     "endAngle": 90,
        #     "track": {
        #       "background": "#e7e7e7",
        #       "strokeWidth": '97%',
        #       "margin": 5,
        #       "dropShadow": {
        #         "enabled": True,
        #         "top": 2,
        #         "left": 0,
        #         "color": '#999',
        #         "opacity": 1,
        #         "blur": 2
        #       }
        #     },
        #     "dataLabels": {

        #       "name": {
        #         "show": False
        #       },
        #       "value": {
        #         "offsetY": -2,
        #         "fontSize": '18px'
        #       }
        #     }
        #   }
        # },
        # "grid": {
        #   "padding": {
        #     "top":10
        #   }
        # },
        
        
        }
        return _options        
    @staticmethod
    def barGrouped (_data,_config):
        """
        """
        options = {"series":[],"chart":{"type":"bar"},"plotOptions": {
          "bar": {
            "horizontal": True,
            "dataLabels": {
              "position": 'top',
            }}},
            
            }
        _yaxis = _config["axis"]["y"]
        for _name in _yaxis :
            options["series"] += [{'name':_name.replace('_',' ').upper(),"data":_data[_name].tolist()}]
        #
        # _xaxis 
        _xaxis = _config['axis']['x']
        options['xaxis'] = {'categories':_data[_xaxis].values.tolist()}
        return options
