# imports

# standard

import math
import random
from numbers import Real
from statistics import mean

import geopandas as gpd

# *****************************************************************************
# *****************************************************************************

# local, internal
from src.topupopt.data.gis.utils import read_gdf_file
from src.topupopt.data.buildings.dk import heat
from src.topupopt.data.buildings.dk import bbr

# *****************************************************************************
# *****************************************************************************

class TestDataBuildingsDK:

    # *************************************************************************
    # *************************************************************************
    
    def test_demand_dict(self):
        
        # heat_demand_dict_by_building_entrance
        
        osm_data_filename = 'tests/data/gdf_osm.gpkg'
        building_data_filename = 'tests/data/gdf_buildings.gpkg'
        bdg_gdf_container_columns = ('ejerskaber','koordinater','bygningspunkt')
        number_time_intervals = 12
        min_to_max_ratio = 0.1
        intraperiod_time_interval_duration = [
            30*24*3600
            for i in range(number_time_intervals)
            ]
        annual_heat_demand_scenario = 1000
        total_area = 1000
        air_temperature_scenario = [10 for i in range(number_time_intervals)]
        
        gdf_osm = gpd.read_file(osm_data_filename)
        gdf_osm.set_index(['element_type', 'osmid'], drop=True, inplace=True)
    
        gdf_buildings = read_gdf_file(
            filename=building_data_filename,
            packed_columns=bdg_gdf_container_columns,
            index='index'
            )
        
        # order by state
        
        heat_demand_dict = heat.heat_demand_dict_by_building_entrance(
            gdf_osm=gdf_osm,
            gdf_buildings=gdf_buildings,
            number_intervals=number_time_intervals,
            time_interval_durations=intraperiod_time_interval_duration,
            bdg_min_to_max_ratio={
                index: min_to_max_ratio for index in gdf_buildings.index
                },
            bdg_specific_demand={
                index: annual_heat_demand_scenario/total_area 
                for index in gdf_buildings.index
                },
            bdg_demand_phase_shift=None,
            avg_state=air_temperature_scenario,
            state_correlates_with_output=False
            )
        assert type(heat_demand_dict) == dict
        assert len(heat_demand_dict) == len(gdf_osm)
        
        # no state preference, use phase shift
    
        heat_demand_dict2 = heat.heat_demand_dict_by_building_entrance(
            gdf_osm=gdf_osm,
            gdf_buildings=gdf_buildings,
            number_intervals=number_time_intervals,
            time_interval_durations=intraperiod_time_interval_duration,
            bdg_min_to_max_ratio={
                index: min_to_max_ratio for index in gdf_buildings.index
                },
            bdg_specific_demand={
                index: annual_heat_demand_scenario/total_area 
                for index in gdf_buildings.index
                },
            bdg_demand_phase_shift={
                index: 2*math.pi*random.random() for index in gdf_buildings.index
                },
            avg_state=None,
            state_correlates_with_output=False
            )
        assert type(heat_demand_dict2) == dict
        assert len(heat_demand_dict2) == len(gdf_osm)
        
        # total heating area
        
        heating_area = heat.total_heating_area(gdf_osm, gdf_buildings)
        assert isinstance(heating_area, Real)
        assert math.isclose(heating_area, 100882, abs_tol=1e-3)
    
    # *************************************************************************
    # *************************************************************************
    
    # def test_bbr(self):
        
    #     # test get_bbr_building_data_geodataframe
        
    #     osm_data_filename = 'tests/data/gdf_osm.gpkg'
                
    #     gdf_osm = gpd.read_file(osm_data_filename)
    #     gdf_osm.set_index(['element_type', 'osmid'], drop=True, inplace=True)
        
    #     error_raised = False
    #     try:
    #         gdf_buildings, drop_list = bbr.get_bbr_building_data_geodataframe(
    #             list(gdf_osm[heat.label_osm_entrance_id]),
    #             None,
    #             None,
    #             None)
    #     except UnboundLocalError:
    #         error_raised = True
    #     assert error_raised
        
    #     # drop the rows with no data
    #     gdf_osm = gdf_osm.drop(
    #         index=[
    #             (gdf_osm[
    #                 gdf_osm[
    #                     heat.label_osm_entrance_id
    #                     ]==bdg_entrance_id].index)[0]
    #             for bdg_entrance_id in drop_list
    #             ]
    #         )

# *****************************************************************************
# *****************************************************************************