# coding=utf-8
import glob
import os
import shutil

import Constants
import FileUtils
from Inventory import Inventory
from InventoryMetadataReader import InventoryMetadataReader
from JobOrderInventoryReader import JobOrderInventoryReader


class InventoryL1C(Inventory):
    """
        Inventory L1C
    """
    def __init__(self, loglevel, logfile, errfile):
        # init logger
        super(InventoryL1C, self).__init__(loglevel, logfile, errfile)

    @staticmethod
    def is_inventory_mode(mode):
        # Inventory L1A DS
        if "L1CFormatDS" in mode or "L1CFormatTL" in mode:
            return True
        return False

    def do_inventory(self, working_dir, gipp_folder, mode, context_manager,
                     output_idp_infos_file, output_icd_file, dateoflogs, nb_tasks):
        """
            main function
        """

        # Get acquisition station from config
        acquisition_station = context_manager.get_acquisition_station()

        # Inventory L1C DS
        if "L1CFormatDS" in mode:
            self._inventory_l1c_ds(context_manager,dateoflogs,gipp_folder,
                                   acquisition_station,output_icd_file,output_idp_infos_file,
                                   working_dir)

        # Inventory L1C TL
        if "L1CFormatTL" in mode:
            self._inventory_l1c_tl(context_manager,dateoflogs,
                                   acquisition_station,working_dir, nb_tasks)
            self._generate_tci_product(context_manager, dateoflogs, working_dir, nb_tasks)

    def _inventory_l1c_ds(self, context_manager, dateoflogs, gipp_folder, acquisition_station,
                          output_icd_file, output_idp_infos_file,
                          working_dir):
        self.logger.info("Doing inventory for L1C Datastrip")
        pdi_ds_output_folder = context_manager.get_element("PROC.L1C.PDI_DS")
        if pdi_ds_output_folder is None:
            raise Exception("No PROC.L1C.PDI_DS in context !!!")
        datastrips_out = glob.glob(os.path.join(pdi_ds_output_folder[0], "S2*DS*"))
        if len(datastrips_out) != 1:
            raise Exception(
                "No or more than one datastrips found in " + os.path.join(pdi_ds_output_folder[0], "S2*"))
        datastrip_out = datastrips_out[0]
        # Inventory working dirs
        inventory_working_dir = os.path.join(working_dir, "ipf_output_inventory_DS_L1C_" + dateoflogs)
        if not os.path.exists(inventory_working_dir):
            FileUtils.create_directory(inventory_working_dir)
        output_folder_inventory = os.path.join(working_dir, "INV_L1C_DS")
        if not os.path.exists(output_folder_inventory):
            FileUtils.create_directory(output_folder_inventory)
        # Find the JobOrder Template
        inv_mtd_l1c_ds_template_filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data",
                                                       "JobOrderTemplates",
                                                       "job_order_inv_mtd_DS_L1C.xml")
        self.logger.debug("JobOrder inventory L1CDS template : " + inv_mtd_l1c_ds_template_filename)
        jo_reader = JobOrderInventoryReader(inv_mtd_l1c_ds_template_filename)
        jo_reader.set_ds_input(datastrip_out)
        jo_reader.set_working_input(inventory_working_dir)
        jo_reader.set_processing_station(Constants.PROCESSING_STATION)
        jo_reader.set_acquisition_station(acquisition_station)
        jo_reader.set_global_footprint(self._get_global_footprint(context_manager))
        # No output really ?
        # jo_reader.set_output(output_folder_inventory)
        inventory_job_order = os.path.join(inventory_working_dir, "JobOrderInventory.xml")
        jo_reader.write_to_file(inventory_job_order)
        # Launch process
        script_path = os.path.join(Constants.INVENTORY_L1_SOFT_FOLDER, Constants.INVENTORY_L1_DS_SCRIPT_NAME)
        self._launch_inventory_process([inventory_job_order],"DS_L1C", script_path)
        # Check if inventory has been generated
        if not os.path.exists(os.path.join(datastrip_out, "Inventory_Metadata.xml")):
            raise Exception("No Inventory_Metadata.xml file generated in "+datastrip_out)
        # Tar the datastrip
        ds_basename = os.path.basename(datastrip_out)
        out_tar_file = os.path.join(output_folder_inventory, ds_basename+".tar")
        self.logger.info("Tar the L1C DS : "+datastrip_out + " to "+out_tar_file)
        # Tar the datastrip
        FileUtils.tar_directory(datastrip_out, out_tar_file)
        # List datastrips in output of inventory
        list_of_ds_produced = glob.glob(os.path.join(output_folder_inventory, "S2*DS*tar"))
        if len(list_of_ds_produced) == 0:
            raise Exception("No datastrip produced in inventory DS L1C : " + output_folder_inventory)
        self.logger.info("Inventory DS L1C done, products can be found in : " + output_folder_inventory)
        # Copy KPI files
        output_folder_kpi = os.path.join(working_dir, "KPI_L1C_DS")
        if not os.path.exists(output_folder_kpi):
            FileUtils.create_directory(output_folder_kpi)
        shutil.copyfile(output_idp_infos_file, os.path.join(output_folder_kpi, os.path.basename(datastrip_out) +
                                                            "_" + dateoflogs + "_" + os.path.basename(
            output_idp_infos_file)))
        shutil.copyfile(output_icd_file, os.path.join(output_folder_kpi, os.path.basename(datastrip_out) +
                                                      "_" + dateoflogs + "_" + os.path.basename(output_icd_file)))
        # Copy the datastrip metadata to the KPI folder
        datastrip_xml_out = glob.glob(os.path.join(datastrip_out, "S2*DS*xml"))[0]
        shutil.copyfile(datastrip_xml_out, os.path.join(output_folder_kpi, os.path.basename(datastrip_xml_out)))
        # Copy the PROBAS file to the KPI
        probas_in = glob.glob(os.path.join(gipp_folder, "S2*PROBAS*"))
        for f in probas_in:
            shutil.copyfile(f, os.path.join(output_folder_kpi, os.path.basename(f)))

    def _inventory_l1c_tl(self, context_manager, dateoflogs, acquisition_station, working_dir, nb_tasks):
        self.logger.info("Doing inventory for L1C Tile")
        pdi_ds_output_folder = context_manager.get_element("PROC.PDI_DS")
        if pdi_ds_output_folder is None:
            raise Exception("No PROC.PDI_DS in context !!!")
        datastrips_out = glob.glob(os.path.join(pdi_ds_output_folder[0], "S2*DS*"))
        if len(datastrips_out) != 1:
            raise Exception(
                "No or more than one datastrips found in " + os.path.join(pdi_ds_output_folder[0], "S2*"))
        datastrip_out = datastrips_out[0]
        pdi_gr_output_folder = context_manager.get_element("PROC.L1C.PDI_DS_TILE_LIST")
        if pdi_gr_output_folder is None:
            raise Exception("No PROC.L1C.PDI_DS_TILE_LIST in context !!!")
        tiles_out = glob.glob(os.path.join(pdi_gr_output_folder[0], "S2*TL*"))
        if len(tiles_out) == 0:
            raise Exception("No tiles found in " + os.path.join(pdi_gr_output_folder[0], "S2*TL*"))
        tile_finalize_tl_list_output = context_manager.get_element_in_proc_list("TILE_FINALIZE", "PROC.LIST.PDI_DS_TILE_LIST")
        print(tile_finalize_tl_list_output)
        if tile_finalize_tl_list_output is None:
            raise Exception("No TILE_FINALIZE found in PROC.LIST.PDI_DS_TILE_LIST")
        for tl in tiles_out:
            self.logger.debug("Handling tile : "+tl)
            # copy the footprint.gml file from TILE_FINALIZE
            FileUtils.copy_tree(os.path.join(tile_finalize_tl_list_output, os.path.basename(tl)), tl,max_depth=5,
                                pattern="footprint.*")
        # Inventory working dirs
        inventory_working_dir = os.path.join(working_dir, "ipf_output_inventory_TL_L1C_" + dateoflogs)
        if not os.path.exists(inventory_working_dir):
            FileUtils.create_directory(inventory_working_dir)
        output_folder_inventory = os.path.join(working_dir, "INV_L1C_TL")
        if not os.path.exists(output_folder_inventory):
            FileUtils.create_directory(output_folder_inventory)
        # Create the job orders
        sensing_start = context_manager.get_sensings_ms()[0]
        sensing_stop = context_manager.get_sensings_ms()[1]
        jobs = self.split_tiles_jobs(tiles_out, inventory_working_dir, acquisition_station,
                                     sensing_start, sensing_stop,
                                     output_folder_inventory, datastrip_out,
                                     nb_tasks)
        # Launch process
        script_path = os.path.join(Constants.INVENTORY_L1_SOFT_FOLDER, Constants.INVENTORY_L1_GR_SCRIPT_NAME)
        self._launch_inventory_process(jobs, "TL_L1C", script_path)
        # Tar the granules
        for tl in tiles_out:
            # Check if inventory has been generated
            if not os.path.exists(os.path.join(tl, "Inventory_Metadata.xml")):
                raise Exception("No Inventory_Metadata.xml file generated in " + tl)
            inventory_mtd_reader = InventoryMetadataReader(os.path.join(tl, "Inventory_Metadata.xml"))
            if inventory_mtd_reader.get_file_id() is None or len(inventory_mtd_reader.get_file_id())==0:
                raise Exception("Inventory_Metadata.xml is not correctly generated for " + tl)
            # Remove VECTOR folder
            if os.path.isdir(os.path.join(tl, "QI_DATA", "VECTOR")):
                shutil.rmtree(os.path.join(tl, "QI_DATA", "VECTOR"))
            tile_tar_filename = os.path.join(output_folder_inventory, os.path.basename(tl)+".tar")
            FileUtils.tar_directory(tl, tile_tar_filename)
        # List produced
        list_of_tl_produced = glob.glob(os.path.join(output_folder_inventory, "S2*TL*tar"))
        if len(list_of_tl_produced) == 0:
            raise Exception("No tiles produced in inventory TL L1C : " + output_folder_inventory)
        # Copy KPI files
        output_folder_kpi = os.path.join(working_dir, "KPI_L1C_TL")
        if not os.path.exists(output_folder_kpi):
           FileUtils.create_directory(output_folder_kpi)
        self.logger.info("Inventory TL L1C done, products can be found in : " + output_folder_inventory)

    def _generate_tci_product(self, context_manager, dateoflogs, working_dir, nb_tasks):
        pdi_gr_output_folder = context_manager.get_element("PROC.L1C.PDI_DS_TILE_LIST")
        if pdi_gr_output_folder is None:
            raise Exception("No PROC.L1C.PDI_DS_TILE_LIST in context !!!")
        tci_tl_output_folder = context_manager.get_element("PROC.PVI.PDI_DS_TCI_LIST")
        if tci_tl_output_folder is None:
            raise Exception("No PROC.PVI.PDI_DS_TCI_LIST in context !!!")
        tiles_out = glob.glob(os.path.join(pdi_gr_output_folder[0], "S2*TL*"))
        if len(tiles_out) == 0:
            raise Exception("No tiles found in " + os.path.join(pdi_gr_output_folder[0], "S2*TL*"))
        output_folder_inventory = os.path.join(working_dir, "INV_L1C_TL")
        if not os.path.exists(output_folder_inventory):
            FileUtils.create_directory(output_folder_inventory)
        # Inventory working dirs
        inventory_working_dir = os.path.join(working_dir, "ipf_output_inventory_TL_TCI_" + dateoflogs)
        for tl in tiles_out:
            self.logger.debug("Handling tile : " + tl)
            tci_filename = os.path.basename(tl).replace("MSI_L1C_TL", "MSI_L1C_TC")
            # Find the jp2 file fr the tile
            tl_tci_jp2 = glob.glob(os.path.join(tci_tl_output_folder[0],
                                                 tci_filename+ ".jp2"))
            if len(tl_tci_jp2) == 0:
                raise Exception("No JP2 file found in "+os.path.join(tci_tl_output_folder[0],
                                                tci_filename + ".jp2"))
            tl_tci_jp2 = tl_tci_jp2[0]
            # Check if inventory has been generated
            if not os.path.exists(os.path.join(tl, "Inventory_Metadata.xml")):
                raise Exception("No Inventory_Metadata.xml file found in " + tl)
            tl_inventory_mtd_file = os.path.join(tl, "Inventory_Metadata.xml")
            tl_tci_folder = os.path.join(inventory_working_dir, tci_filename)
            if not os.path.exists(tl_tci_folder):
                FileUtils.create_directory(tl_tci_folder)
            FileUtils.copy_file(tl_tci_jp2, os.path.join(tl_tci_folder, os.path.basename(tl_tci_jp2)))
            tci_inventory_mtd_file = os.path.join(tl_tci_folder, "Inventory_Metadata.xml")
            inventory_mtd_reader = InventoryMetadataReader(tl_inventory_mtd_file)
            inventory_mtd_reader.set_file_id(inventory_mtd_reader.get_file_id().replace("MSI_L1C_TL", "MSI_L1C_TC"))
            inventory_mtd_reader.set_file_name(inventory_mtd_reader.get_file_name().replace("MSI_L1C_TL", "MSI_L1C_TC"))
            inventory_mtd_reader.set_file_type(inventory_mtd_reader.get_file_type().replace("MSI_L1C_TL", "MSI_L1C_TC"))
            self.logger.info("Writing tci inventory metadata in "+tci_inventory_mtd_file)
            inventory_mtd_reader.write_to_file(tci_inventory_mtd_file)
            tile_tar_filename = os.path.join(output_folder_inventory, os.path.basename(tci_filename) + ".tar")
            self.logger.debug("Tar the tci "+tl_tci_folder +" to " +tile_tar_filename)
            FileUtils.tar_directory(tl_tci_folder, tile_tar_filename)
        # List produced
        list_of_tl_produced = glob.glob(os.path.join(output_folder_inventory, "S2*TC*tar"))
        if len(list_of_tl_produced) == 0:
            raise Exception("No tiles produced in inventory TCI L1C : " + output_folder_inventory)
        self.logger.info("Inventory TCI L1C done, products can be found in : " + output_folder_inventory)


