from dataclasses import dataclass
from typing import List, Optional, Union

from .common import CostAmount, DescriptionV1, Measurement


@dataclass
class EnergyElement:
    description: DescriptionV1
    energy_efficiency_rating: int
    environmental_efficiency_rating: int


@dataclass
class InstantaneousWwhrs:
    rooms_with_bath_and_or_shower: int
    rooms_with_mixer_shower_no_bath: int
    rooms_with_bath_and_mixer_shower: int


@dataclass
class MainHeatingDetail:
    has_fghrs: str
    main_fuel_type: int
    heat_emitter_type: int
    emitter_temperature: Union[int, str]
    main_heating_number: int
    main_heating_control: int
    main_heating_category: int
    main_heating_fraction: int
    main_heating_data_source: int
    boiler_flue_type: Optional[int] = None
    fan_flue_present: Optional[str] = None
    central_heating_pump_age: Optional[int] = None
    main_heating_index_number: Optional[int] = None
    sap_main_heating_code: Optional[int] = None


@dataclass
class SapHeating:
    cylinder_size: int
    water_heating_code: int
    water_heating_fuel: int
    instantaneous_wwhrs: InstantaneousWwhrs
    main_heating_details: List[MainHeatingDetail]
    immersion_heating_type: Union[int, str]
    has_fixed_air_conditioning: str
    cylinder_insulation_type: Optional[int] = None
    cylinder_thermostat: Optional[str] = None
    secondary_fuel_type: Optional[int] = None
    secondary_heating_type: Optional[int] = None
    cylinder_insulation_thickness: Optional[int] = None


@dataclass
class PhotovoltaicSupplyNoneOrNoDetails:
    pv_connection: int
    percent_roof_area: int


@dataclass
class PhotovoltaicSupply:
    none_or_no_details: PhotovoltaicSupplyNoneOrNoDetails


@dataclass
class SapEnergySource:
    mains_gas: str
    meter_type: int
    photovoltaic_supply: PhotovoltaicSupply
    wind_turbines_count: int
    wind_turbines_terrain_type: int


@dataclass
class SapFloorDimension:
    floor: int
    room_height: Measurement
    total_floor_area: Measurement
    party_wall_length: Union[Measurement, int]
    heat_loss_perimeter: Measurement
    floor_insulation: Optional[int] = None
    floor_construction: Optional[int] = None


@dataclass
class SapRoomInRoof:
    floor_area: Measurement
    insulation: str
    roof_room_connected: str
    construction_age_band: str


@dataclass
class SapBuildingPart:
    identifier: str
    wall_dry_lined: str
    wall_thickness: int
    floor_heat_loss: int
    roof_construction: int
    wall_construction: int
    building_part_number: int
    sap_floor_dimensions: List[SapFloorDimension]
    wall_insulation_type: int
    construction_age_band: str
    party_wall_construction: Union[int, str]
    wall_thickness_measured: str
    roof_insulation_location: Union[int, str]
    roof_insulation_thickness: Union[str, int]
    sap_room_in_roof: Optional[SapRoomInRoof] = None
    wall_insulation_thickness: Optional[str] = None
    floor_insulation_thickness: Optional[str] = None
    flat_roof_insulation_thickness: Optional[Union[str, int]] = None


@dataclass
class SapFlatDetails:
    level: int
    top_storey: str
    flat_location: int
    heat_loss_corridor: int


@dataclass
class WindowsTransmissionDetails:
    u_value: float
    data_source: int
    solar_transmittance: float


@dataclass
class ImprovementDetails:
    improvement_number: int


@dataclass
class SuggestedImprovement:
    sequence: int
    typical_saving: CostAmount
    indicative_cost: str
    improvement_type: str
    improvement_details: ImprovementDetails
    improvement_category: int
    energy_performance_rating: int
    environmental_impact_rating: int


@dataclass
class AlternativeImprovement:
    sequence: int
    typical_saving: CostAmount
    improvement_type: str
    improvement_details: ImprovementDetails
    improvement_category: int
    energy_performance_rating: int
    environmental_impact_rating: int


@dataclass
class RenewableHeatIncentive:
    water_heating: int
    space_heating_existing_dwelling: int
    impact_of_loft_insulation: Optional[int] = None
    impact_of_solid_wall_insulation: Optional[int] = None


@dataclass
class RdSapSchema19_0:
    uprn: int
    roofs: List[EnergyElement]
    walls: List[EnergyElement]
    floors: List[EnergyElement]
    status: str
    tenure: int
    window: EnergyElement
    lighting: EnergyElement
    postcode: str
    hot_water: EnergyElement
    post_town: str
    built_form: int
    door_count: int
    glazed_area: int
    region_code: int
    report_type: int
    sap_heating: SapHeating
    sap_version: float
    schema_type: str
    uprn_source: str
    country_code: str
    main_heating: List[EnergyElement]
    dwelling_type: DescriptionV1
    language_code: int
    property_type: int
    address_line_1: str
    assessment_type: str
    completion_date: str
    inspection_date: str
    extensions_count: int
    measurement_type: int
    total_floor_area: int
    transaction_type: int
    conservatory_type: int
    heated_room_count: int
    pvc_window_frames: str
    registration_date: str
    sap_energy_source: SapEnergySource
    secondary_heating: EnergyElement
    lzc_energy_sources: List[int]
    sap_building_parts: List[SapBuildingPart]
    low_energy_lighting: int
    solar_water_heating: str
    habitable_room_count: int
    heating_cost_current: CostAmount
    insulated_door_count: int
    co2_emissions_current: float
    energy_rating_average: int
    energy_rating_current: int
    lighting_cost_current: CostAmount
    main_heating_controls: List[EnergyElement]
    multiple_glazing_type: int
    open_fireplaces_count: int
    has_hot_water_cylinder: str
    heating_cost_potential: CostAmount
    hot_water_cost_current: CostAmount
    mechanical_ventilation: int
    percent_draughtproofed: int
    suggested_improvements: List[SuggestedImprovement]
    co2_emissions_potential: float
    energy_rating_potential: int
    lighting_cost_potential: CostAmount
    schema_version_original: str
    hot_water_cost_potential: CostAmount
    renewable_heat_incentive: RenewableHeatIncentive
    windows_transmission_details: WindowsTransmissionDetails
    energy_consumption_current: int
    has_fixed_air_conditioning: str
    multiple_glazed_proportion: int
    calculation_software_version: str
    energy_consumption_potential: int
    environmental_impact_current: int
    fixed_lighting_outlets_count: int
    current_energy_efficiency_band: str
    environmental_impact_potential: int
    has_heated_separate_conservatory: str
    potential_energy_efficiency_band: str
    co2_emissions_current_per_floor_area: int
    low_energy_fixed_lighting_outlets_count: int
    sap_flat_details: Optional[SapFlatDetails] = None
    address_line_2: Optional[str] = None
    glazing_gap: Optional[Union[str, int]] = None
    alternative_improvements: Optional[List[AlternativeImprovement]] = None
