'''
Created on 12-Jul-2021

@author: bthakur
'''
import random
import inspect
import traceback
import re

import numpy as np


from xv.km.util import latex_fraction
from xv.util import toIntOrFloat

class ArithmeticGridHelper:
    def __init__(self, **kwargs):
        self.verbose = kwargs.get('verbose', False)
        pass
    
    def get_problem_max_cost(self, cost_data):
        return self._get_problem_min_max_cost(cost_data, 'max')
        pass
    
    def get_problem_min_cost(self, cost_data):
        return self._get_problem_min_max_cost(cost_data, 'min')
        pass
    
    def _get_problem_min_max_cost(self, cost_data, cost_type):
        item_arr = cost_data.get('item_arr', None)
        person_arr = cost_data.get('person_arr', None)
        qty_arr = cost_data.get('qty_arr', None)
        price_arr = cost_data.get('price_arr', None)
        cost_arr = qty_arr * price_arr
        
        axis = random.randint(0, 1)
        cost_arr = cost_arr.sum(axis = axis)
        
        if cost_type == 'max':
            max_min_cost = max(cost_arr)
            if axis == 1:
                statement = 'Which person has spent the most?'
                answer_statement = 'Person with the most spending'
                names = person_arr
            else:
                statement = 'Which item has the highest cost in total?'
                answer_statement = 'Item with the highest cost'
                names = item_arr
        else:
            max_min_cost = min(cost_arr)
            if axis == 1:
                statement = 'Which person has spent the least?'
                answer_statement = 'Person with the least spending'
                names = person_arr
            else:
                statement = 'Which item has the lowest cost in total?'
                answer_statement = 'Item with the lowest cost'
                names = item_arr
            pass
            
        max_min_cost_names = [names[i]
                        for (i, x) in enumerate(cost_arr) 
                        if x == max_min_cost] 
        
        max_min_cost_names = ", ".join(max_min_cost_names)
        
        result = {
            'statement': statement,
            'names': max_min_cost_names,
            'cost': max_min_cost,
            'answer_statement': answer_statement,
            'answer': f"{max_min_cost_names}: {max_min_cost}"
            }
        return result
        pass
    
    def _get_css_style(self):
        sStyle = """
            <style>
            table{
              border-collapse: collapse;
              margin-bottom: 50px;
            }
    
            .td_cell {
              border: 1px solid grey !important;
              border-collapse: collapse;
              text-align: center !important;
              padding: 10px;
            }
    
            .no_border{
              border: none !important;
            }
    
            .col_header, .row_header{
              white-space: nowrap;
              font-weight: bold;
            }
    
            .row_header{
              color: blue;
            }
    
            .col_header{
              color: red;
              text-align: center !important;
            }

            .priority{
                color: blue;
                width: auto;
                padding-left: 10px;
            }
    
            </style>
            """
        
        return sStyle
        pass

    def get_qty_grid(self, size, **kwargs):
        '''
        @size
        @cost_data
        @grid_type = 'qty' #other values = 'cost' 
        '''
        cost_data = kwargs.get('cost_data', None)
        grid_type = kwargs.get('grid_type', "qty")
        
        show_price = kwargs.get('show_price', False)
        show_item_cost = kwargs.get('show_item_cost', False)
        show_person_cost = kwargs.get('show_person_cost', False)
        
        if cost_data is None:
            cost_data = self.get_random_arr(size)

        item_arr = cost_data.get('item_arr', None)
        person_arr = cost_data.get('person_arr', None)
        qty_arr = cost_data.get('qty_arr', None)
        price_arr = cost_data.get('price_arr', None)
        cost_arr = qty_arr * price_arr
        
        person_cost_arr = cost_arr.sum(axis = 1)
        item_cost_arr = cost_arr.sum(axis = 0)
            
        sTable = []
        sTable.append(self._get_css_style())
        sTable.append("<table>")

        header_tr = self._get_item_arr_tr(item_arr, price_arr, show_price)
        sTable.append(header_tr)
        
        
        for i in range(size[0]):
            
            sTable.append("<tr>")
            
            #person_name
            sTable.append("<td class = 'row_header no_border'>")
            sTable.append(person_arr[i])
            sTable.append("</td>")
            
            for j in range(size[1]):
                if grid_type == 'cost':
                    sTable.append("<td class = 'td_cell' >")
                    if show_price:
                        sTable.append(f"{qty_arr[i][j]} * {price_arr[j]} = {cost_arr[i][j]}")
                    else:
                        sTable.append(f"{cost_arr[i][j]}")
                        
                    sTable.append("</td>")
                else:
                    sTable.append("<td class = 'td_cell' >")
                    sTable.append(f"{qty_arr[i][j]}")
                    sTable.append("</td>")
                    pass
                pass

            #sum of persons spending            
            if show_person_cost:
                sTable.append("<td class = 'row_header no_border'>")
                sTable.append(f"{person_cost_arr[i]}")
                sTable.append("</td>")
            else:
                sTable.append("<td class = 'row_header no_border'>")
                sTable.append(f"&nbsp;")
                sTable.append("</td>")
                pass
                
                
            sTable.append("</tr>")
    
            pass


        #col wise sum
        if show_item_cost:
            sTable.append("</tr>")
            sTable.append("<td>")
            sTable.append("</td>")
            
            for item_cost in item_cost_arr:
                sTable.append("<td class = 'col_header no_border'>")
                sTable.append(f"{item_cost}")
                sTable.append("</td>")
                pass
            
            sTable.append("<td class = 'col_header no_border'>")
            sTable.append(f"{sum(item_cost_arr)}")
            sTable.append("</td>")
            
            sTable.append("</tr>")
            pass
        
        
        sTable.append("</table>")
        sTable = "".join(sTable)
        sTable = sTable.replace("\n", "")
        
        
        grid = {}
        grid['cost_data'] = cost_data
        grid['grid_html'] = sTable
        return grid
        pass
    
    def get_random_arr(self, size):
        cost_data = {}
        cost_data['item_arr'] = self._get_item_arr(size[1])
        cost_data['person_arr'] = self._get_person_arr(size[0])
        cost_data['qty_arr'] = self._get_qty_arr(size = size)
        cost_data['price_arr'] = self._get_price_arr(size = size[1])
        return cost_data
        pass
    
    def _get_item_arr_tr(self, item_arr, price_arr, show_price):
        tr = []
        tr.append("<tr>")
        tr.append("<td class = 'col_header no_border'>")
        tr.append("&nbsp;<br/>Price:")
        tr.append("</td>")
        
        for i, item_name in enumerate(item_arr):
            tr.append("<td class = 'col_header no_border'>")
            if show_price:
                tr.append(f"{item_name}<br/>{price_arr[i]}")
            else:
                tr.append(f"{item_name}")
                
            tr.append("</td>")
        
        tr.append("</tr>")
        tr = "".join(tr)
        return tr
        pass

    
    def _get_item_arr(self, count):
        item_arr = ['cake', 
                      'pizza',
                      'ice-cream',
                      'chocolate',
                      'burger',
                      'cold-drink',
                      ]
        
        if count > len(item_arr):
            raise Exception(f"count {count} is more than max number of items.")


        return random.sample(item_arr, count)
        pass

    def _get_person_arr(self, count):
        person_arr = ['John', 
                      'Mary',
                      'Neena',
                      'Hariot',
                      'Tom',
                      'Julie',
                      'James',
                      ]
        
        if count > len(person_arr):
            raise Exception(f"count {count} is more than max number of persons.")


        return random.sample(person_arr, count)
        pass

    def _get_qty_arr(self, size = (3, 3), low = 1, high = 10):
        qty_arr = np.random.randint(low, high, size = size)
        return qty_arr
        pass
    
    def _get_price_arr(self, size = 3, low = 1, high = 10):
        price_arr = np.random.randint(low, high, size = size)
        return price_arr
        pass
    
    pass
#class ArithmeticGridHelper:
