# generated by datamodel-codegen:
#   filename:  lcax.schema.json

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel, Extra, Field


class BuildingModelScope(BaseModel):
    class Config:
        allow_population_by_field_name = True

    building_services: bool
    external_works: bool
    facilitating_works: bool
    ff_e: bool
    finishes: bool
    substructure: bool
    superstructure_envelope: bool
    superstructure_frame: bool
    superstructure_internal_elements: bool


class BuildingType(Enum):
    renovation = 'renovation'
    new = 'new'


class BuildingTypology(Enum):
    office = 'office'
    residential = 'residential'
    public = 'public'
    commercial = 'commercial'
    industrial = 'industrial'
    infrastructure = 'infrastructure'
    agricultural = 'agricultural'
    other = 'other'


class Classification(BaseModel):
    class Config:
        allow_population_by_field_name = True

    code: str
    name: str
    system: str


class ExternalImpactData(BaseModel):
    class Config:
        allow_population_by_field_name = True

    format: str
    url: str
    version: Optional[str] = None


class ImpactCategory(BaseModel):
    class Config:
        allow_population_by_field_name = True

    a1a3: Optional[float] = None
    a4: Optional[float] = None
    a5: Optional[float] = None
    b1: Optional[float] = None
    b2: Optional[float] = None
    b3: Optional[float] = None
    b4: Optional[float] = None
    b5: Optional[float] = None
    b6: Optional[float] = None
    b7: Optional[float] = None
    c1: Optional[float] = None
    c2: Optional[float] = None
    c3: Optional[float] = None
    c4: Optional[float] = None
    d: Optional[float] = None


class ImpactCategoryKey(Enum):
    gwp = 'gwp'
    odp = 'odp'
    ap = 'ap'
    ep = 'ep'
    pocp = 'pocp'
    adpe = 'adpe'
    adpf = 'adpf'
    penre = 'penre'
    pere = 'pere'
    perm = 'perm'
    pert = 'pert'
    penrt = 'penrt'
    penrm = 'penrm'
    sm = 'sm'
    rsf = 'rsf'
    nrsf = 'nrsf'
    fw = 'fw'
    hwd = 'hwd'
    nhwd = 'nhwd'
    rwd = 'rwd'
    cru = 'cru'
    mrf = 'mrf'
    mer = 'mer'
    eee = 'eee'
    eet = 'eet'


class ImpactDataSource2(BaseModel):
    class Config:
        extra = Extra.forbid
        allow_population_by_field_name = True

    externalimpactdata: ExternalImpactData


class InternalImpactData(BaseModel):
    class Config:
        allow_population_by_field_name = True

    path: str


class LifeCycleStage(Enum):
    a1a3 = 'a1a3'
    a4 = 'a4'
    a5 = 'a5'
    b1 = 'b1'
    b2 = 'b2'
    b3 = 'b3'
    b4 = 'b4'
    b5 = 'b5'
    b6 = 'b6'
    b7 = 'b7'
    c1 = 'c1'
    c2 = 'c2'
    c3 = 'c3'
    c4 = 'c4'
    d = 'd'


class Location(BaseModel):
    class Config:
        allow_population_by_field_name = True

    address: Optional[str] = None
    city: Optional[str] = None
    country: str


class ProjectInfo2(BaseModel):
    class Config:
        extra = Extra.forbid
        allow_population_by_field_name = True

    infrastructureinfo: Dict[str, str]


class ProjectPhase(Enum):
    design = 'design'
    ongoing = 'ongoing'
    built = 'built'
    other = 'other'


class SoftwareInfo(BaseModel):
    class Config:
        allow_population_by_field_name = True

    calculation_type: Optional[str] = Field(None, alias='calculationType')
    goal_and_scope_definition: Optional[str] = Field(
        None, alias='goalAndScopeDefinition'
    )
    lca_software: str = Field(..., alias='lcaSoftware')


class Source(BaseModel):
    class Config:
        allow_population_by_field_name = True

    name: str
    url: Optional[str] = None


class Standard(Enum):
    en15804_a1 = 'EN15804A1'
    en15804_a2 = 'EN15804A2'
    unknown = 'UNKNOWN'


class SubType(Enum):
    generic = 'Generic'
    specific = 'Specific'
    industry = 'Industry'
    representative = 'Representative'


class Unit(Enum):
    m = 'M'
    m2 = 'M2'
    m3 = 'M3'
    kg = 'KG'
    tones = 'TONES'
    pcs = 'PCS'
    l = 'L'
    m2_r1 = 'M2R1'
    km = 'KM'
    tones_km = 'TONES_KM'
    unknown = 'UNKNOWN'


class BuildingInfo(BaseModel):
    class Config:
        allow_population_by_field_name = True

    building_completion_year: int = Field(..., alias='buildingCompletionYear', ge=0)
    building_mass: str = Field(..., alias='buildingMass')
    building_model_scope: Optional[BuildingModelScope] = Field(
        None, alias='buildingModelScope'
    )
    building_type: BuildingType = Field(..., alias='buildingType')
    building_typology: BuildingTypology = Field(..., alias='buildingTypology')
    certifications: str
    energy_class: str = Field(..., alias='energyClass')
    energy_demand_electricity: float = Field(..., alias='energyDemandElectricity')
    energy_demand_heating: float = Field(..., alias='energyDemandHeating')
    energy_supply_electricity: float = Field(..., alias='energySupplyElectricity')
    energy_supply_heating: float = Field(..., alias='energySupplyHeating')
    exported_electricity: float = Field(..., alias='exportedElectricity')
    floors_above_ground: int = Field(..., alias='floorsAboveGround', ge=0)
    floors_below_ground: int = Field(..., alias='floorsBelowGround', ge=0)
    frame_type: str = Field(..., alias='frameType')
    gross_floor_area: float = Field(..., alias='grossFloorArea')
    gross_floor_area_definition: str = Field(..., alias='grossFloorAreaDefinition')
    heated_floor_area: float = Field(..., alias='heatedFloorArea')
    heated_floor_area_definition: str = Field(..., alias='heatedFloorAreaDefinition')


class Conversion(BaseModel):
    class Config:
        allow_population_by_field_name = True

    meta_data: str
    to: Unit
    value: float


class EPD(BaseModel):
    class Config:
        allow_population_by_field_name = True

    adpe: Optional[ImpactCategory] = None
    adpf: Optional[ImpactCategory] = None
    ap: Optional[ImpactCategory] = None
    comment: Optional[str] = None
    conversions: Optional[List[Conversion]] = None
    cru: Optional[ImpactCategory] = None
    declared_unit: Unit
    eee: Optional[ImpactCategory] = None
    eet: Optional[ImpactCategory] = None
    ep: Optional[ImpactCategory] = None
    format_version: str
    fw: Optional[ImpactCategory] = None
    gwp: Optional[ImpactCategory] = None
    hwd: Optional[ImpactCategory] = None
    id: str
    location: str
    mer: Optional[ImpactCategory] = None
    meta_data: Optional[Dict[str, Any]] = None
    mfr: Optional[ImpactCategory] = None
    name: str
    nhwd: Optional[ImpactCategory] = None
    nrsf: Optional[ImpactCategory] = None
    odp: Optional[ImpactCategory] = None
    penre: Optional[ImpactCategory] = None
    penrm: Optional[ImpactCategory] = None
    penrt: Optional[ImpactCategory] = None
    pere: Optional[ImpactCategory] = None
    perm: Optional[ImpactCategory] = None
    pert: Optional[ImpactCategory] = None
    pocp: Optional[ImpactCategory] = None
    published_date: datetime
    reference_service_life: Optional[int] = Field(None, ge=0)
    rsf: Optional[ImpactCategory] = None
    rwd: Optional[ImpactCategory] = None
    sm: Optional[ImpactCategory] = None
    source: Optional[Source] = None
    standard: Standard
    subtype: SubType
    valid_until: datetime
    version: str


class ImpactDataSource1(BaseModel):
    class Config:
        extra = Extra.forbid
        allow_population_by_field_name = True

    epd: EPD


class ImpactDataSource3(BaseModel):
    class Config:
        extra = Extra.forbid
        allow_population_by_field_name = True

    internalimpactdata: InternalImpactData


class ProjectInfo1(BaseModel):
    class Config:
        extra = Extra.forbid
        allow_population_by_field_name = True

    buildinginfo: BuildingInfo


class Transport(BaseModel):
    class Config:
        allow_population_by_field_name = True

    distance: float
    distance_unit: Unit = Field(..., alias='distanceUnit')
    id: str
    name: str
    transport_epd: Union[ImpactDataSource1, ImpactDataSource2, ImpactDataSource3] = (
        Field(..., alias='transportEpd')
    )


class Product(BaseModel):
    class Config:
        allow_population_by_field_name = True

    description: str
    id: str
    impact_data: Union[ImpactDataSource1, ImpactDataSource2, ImpactDataSource3] = Field(
        ..., alias='impactData'
    )
    meta_data: Optional[Dict[str, Any]] = Field(None, alias='metaData')
    name: str
    quantity: float
    reference_service_life: int = Field(..., alias='referenceServiceLife', ge=0)
    results: Optional[Dict[str, Any]] = None
    transport: Optional[Transport] = None
    unit: Unit


class Assembly(BaseModel):
    class Config:
        allow_population_by_field_name = True

    category: Optional[str] = None
    classification: Optional[List[Classification]] = None
    comment: Optional[str] = None
    description: str
    id: str
    meta_data: Optional[Dict[str, Any]] = Field(None, alias='metaData')
    name: str
    products: Dict[str, Product]
    quantity: float
    results: Optional[Dict[str, Any]] = None
    unit: Unit


class LCAxProject(BaseModel):
    class Config:
        allow_population_by_field_name = True

    assemblies: Dict[str, Assembly]
    classification_system: Optional[str] = Field(None, alias='classificationSystem')
    comment: Optional[str] = None
    description: Optional[str] = None
    format_version: str = Field(..., alias='formatVersion')
    id: str
    impact_categories: List[ImpactCategoryKey] = Field(..., alias='impactCategories')
    lcia_method: Optional[str] = Field(None, alias='lciaMethod')
    life_cycle_stages: List[LifeCycleStage] = Field(..., alias='lifeCycleStages')
    location: Location
    meta_data: Optional[Dict[str, Any]] = Field(None, alias='metaData')
    name: str
    owner: Optional[str] = None
    project_info: Optional[Union[ProjectInfo1, ProjectInfo2]] = Field(
        None, alias='projectInfo'
    )
    project_phase: ProjectPhase = Field(..., alias='projectPhase')
    reference_study_period: Optional[int] = Field(
        None, alias='referenceStudyPeriod', ge=0
    )
    results: Optional[Dict[str, Any]] = None
    software_info: SoftwareInfo = Field(..., alias='softwareInfo')
