#
# Copyright The NOMAD Authors.
#
# This file is part of NOMAD. See https://nomad-lab.eu for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from nomad.datamodel.metainfo.eln import Process
from nomad.parsing.tabular import TableData
from nomad.datamodel.metainfo.eln import Sample
from nomad.datamodel.metainfo.eln import Instrument
from nomad.datamodel.metainfo.eln import Chemical
from nomad.datamodel.data import EntryData
import numpy as np
from structlog.stdlib import (
    BoundLogger,
)
from nomad.metainfo import (
    Package,
    Quantity,
    SubSection,
    MEnum,
    Section,
)
from nomad.datamodel.data import (
    EntryData,
    ArchiveSection,
)

m_package = Package(name='Electronic Lab Notebook example schema')


class MyChemical(Chemical, EntryData, ArchiveSection):
    '''
    This is an example description for Chemical.
    A description can contain **markdown** markup and TeX formulas, like $\\sum\\limits_{i=0}^{n}$.
    '''
    m_def = Section(
        label="Instrument",
    )
    form = Quantity(
        type=MEnum(['crystalline solid', 'powder']),
        a_eln={
            "component": "EnumEditQuantity"
        },
    )
    cas_number = Quantity(
        type=str,
        a_eln={
            "component": "StringEditQuantity"
        },
    )
    ec_number = Quantity(
        type=str,
        a_eln={
            "component": "StringEditQuantity"
        },
    )

    def normalize(self, archive, logger: BoundLogger) -> None:
        '''
        The normalizer for the `MyChemical` class.

        Args:
            archive (EntryArchive): The archive containing the section that is being
            normalized.
            logger (BoundLogger): A structlog logger.
        '''
        super(MyChemical, self).normalize(archive, logger)


class MyInstrument(Instrument, EntryData, ArchiveSection):
    '''
    Class autogenerated from yaml schema.
    '''
    m_def = Section(
        label="Instrument",
    )

    def normalize(self, archive, logger: BoundLogger) -> None:
        '''
        The normalizer for the `MyInstrument` class.

        Args:
            archive (EntryArchive): The archive containing the section that is being
            normalized.
            logger (BoundLogger): A structlog logger.
        '''
        super(MyInstrument, self).normalize(archive, logger)


class MyProcess(Process, ArchiveSection):
    '''
    Class autogenerated from yaml schema.
    '''
    m_def = Section(
        label="Process",
    )
    instrument = Quantity(
        type=MyInstrument,
        a_eln={
            "component": "ReferenceEditQuantity"
        },
    )

    def normalize(self, archive, logger: BoundLogger) -> None:
        '''
        The normalizer for the `MyProcess` class.

        Args:
            archive (EntryArchive): The archive containing the section that is being
            normalized.
            logger (BoundLogger): A structlog logger.
        '''
        super(MyProcess, self).normalize(archive, logger)


class PvdEvaporation(MyProcess, TableData, ArchiveSection):
    '''
    Class autogenerated from yaml schema.
    '''
    m_def = Section(
        a_eln={
            "overview": True,
            "hide": [
                "name",
                "lab_id",
                "description",
                "method"
            ]
        },
        a_plot={
            "title": "Pressure and Temperature over Time",
            "x": "time",
            "y": [
                "chamber_pressure",
                "substrate_temperature"
            ]
        },
    )
    data_file = Quantity(
        type=str,
        description='''
        A reference to an uploaded .csv produced by the PVD evaporation instruments
        control software.
        ''',
        a_tabular_parser={
            "sep": "\\t",
            "comment": "#"
        },
        a_browser={
            "adaptor": "RawFileAdaptor"
        },
        a_eln={
            "component": "FileEditQuantity"
        },
    )
    time = Quantity(
        type=np.float64,
        a_tabular={
            "name": "Process Time in seconds"
        },
        shape=["*"],
        unit="s",
    )
    chamber_pressure = Quantity(
        type=np.float64,
        a_tabular={
            "name": "Vacuum Pressure1"
        },
        a_plot={
            "x": "time",
            "y": "chamber_pressure"
        },
        shape=["*"],
        unit="mbar",
    )
    substrate_temperature = Quantity(
        type=np.float64,
        a_tabular={
            "name": "Substrate PV",
            "unit": "degC"
        },
        a_plot={
            "x": "time",
            "y": "substrate_temperature"
        },
        shape=["*"],
        unit="kelvin",
    )


class HotplateAnnealing(MyProcess, ArchiveSection):
    '''
    Class autogenerated from yaml schema.
    '''
    m_def = Section(
        a_eln={
            "overview": True,
            "hide": [
                "name",
                "lab_id",
                "description"
            ]
        },
    )
    set_temperature = Quantity(
        type=np.float64,
        a_eln={
            "component": "NumberEditQuantity"
        },
        unit="K",
    )
    duration = Quantity(
        type=np.float64,
        a_eln={
            "component": "NumberEditQuantity"
        },
        unit="s",
    )


class Processes(ArchiveSection):
    '''
    Class autogenerated from yaml schema.
    '''
    m_def = Section(
        a_eln=None,
    )
    pvd_evaporation = SubSection(
        section_def=PvdEvaporation,
    )
    hotplate_annealing = SubSection(
        section_def=HotplateAnnealing,
    )


class MySample(Sample, EntryData, ArchiveSection):
    '''
    Class autogenerated from yaml schema.
    '''
    m_def = Section(
        a_template={
            "processes": {
                "pvd_evaporation": {}
            }
        },
        label="Sample",
    )
    name = Quantity(
        type=str,
        a_eln={
            "component": "StringEditQuantity"
        },
        default="Default Sample Name",
    )
    tags = Quantity(
        type=MEnum(['internal', 'collaboration', 'project', 'other']),
        a_eln={
            "component": "AutocompleteEditQuantity"
        },
        shape=["*"],
    )
    chemicals = Quantity(
        type=MyChemical,
        a_eln={
            "component": "ReferenceEditQuantity"
        },
        shape=["*"],
    )
    substrate_type = Quantity(
        type=MEnum(['Fused quartz glass', 'SLG', 'other']),
        a_eln={
            "component": "RadioEnumEditQuantity"
        },
    )
    substrate_thickness = Quantity(
        type=np.float64,
        a_eln={
            "component": "NumberEditQuantity"
        },
        unit="m",
    )
    sample_is_from_collaboration = Quantity(
        type=bool,
        a_eln={
            "component": "BoolEditQuantity"
        },
    )
    processes = SubSection(
        section_def=Processes,
    )

    def normalize(self, archive, logger: BoundLogger) -> None:
        '''
        The normalizer for the `MySample` class.

        Args:
            archive (EntryArchive): The archive containing the section that is being
            normalized.
            logger (BoundLogger): A structlog logger.
        '''
        super(MySample, self).normalize(archive, logger)


m_package.__init_metainfo__()
