# -*- coding: utf-8 -*-
import os, posixpath
from . import jpDataUtils
from .jpdata_muni import jpDataMuni
from .jpdata_settings import jpDataSettings
from .i18n import TR


class jpDataLNI:
    _instance = None

    @classmethod
    def instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    def __init__(self):
        self.download_fullpath = ""
        self.lang = "j"
        self.settings = jpDataSettings.instance()
        self.records = None
        self.record = None
        self.source_csv = ""
        self.source = []
        self.current_name = ""
        self.prev_name = ""
        self.current_source_name = ""
        self._Muni = jpDataMuni.instance()

    def init(self):
        if self.records is None:
            self.load_records()

    def _clear_record(self):
        self.record = {
            "name_map": "",
            "code_map": "",
            "type_muni": "",
            "csv": "",
            "year": "",
            "name_pref": "",
            "code_pref": "",
            "name_muni": "",
            "code_muni": "",
            "code_mesh": "",
            "detail": "",
            "url": "",
            "zip": "",
            "shp": "",
            "zip_fullpath": "",
            "shp_fullpath": "",
            "altdir": "",
            "qml": "",
            "epsg": "",
            "encoding": "CP932",
            "download_fullpath": "",
            "subfolder": "",
        }

    def set_download_folder(self, download_fullpath):
        self.download_fullpath = download_fullpath

    def set_lang(self, lang):
        self.lang = lang[:1].lower()

    def load_records(self):
        self.records = jpDataUtils.get_records_from_csv(
            "LandNumInfo.csv", "name_" + self.settings.lang1
        )

    def set_record(
        self,
        name_map,
        year=None,
        name_pref=None,
        name_muni=None,
        code_mesh=None,
        detail=None,
    ):
        if name_map is None:
            jpDataUtils.printDebugLog("jpdata_lni.py: the argument name_map is None.")
            return
        self._clear_record()
        self.record["name_map"] = name_map
        self.record["year"] = year
        self.record["name_pref"] = name_pref
        self.record["code_pref"] = (
            jpDataUtils.getPrefCodeByName(name_pref) if name_pref is not None else ""
        )
        self.record["name_muni"] = name_muni
        self.record["code_muni"] = self._Muni.get_code_muni(name_pref, name_muni)
        self.record["code_mesh"] = code_mesh
        self.record["detail"] = detail
        _record = self.records[name_map]
        self.record["code_map"] = _record["code_map"]
        self.record["type_muni"] = _record["type_muni"]
        self.record["csv"] = (
            _record["year"] if _record["year"][-4:].upper() == ".CSV" else ""
        )
        self.record["url"] = _record["url"]
        self.record["zip"] = _record["zip"]
        self.record["shp"] = _record["shp"]
        self.record["altdir"] = _record["altdir"]
        self.record["source"] = _record["source"]
        self.record["qml"] = _record["qml"]
        self.record["epsg"] = _record["epsg"]
        self.record["encoding"] = _record["encoding"]
        self.record["subfolder"] = self.record["code_map"]
        self.record["download_fullpath"] = posixpath.join(
            self.settings.folder_path, self.record["subfolder"]
        )
        self.prev_name = self.current_name
        self.current_name = name_map
        if self.record["csv"] != "":
            self._load_source(name_map)
            self._set_record_from_source()
        code_pref_or_mesh1 = self.record["code_pref"]
        if self.record["type_muni"] == "mesh1":
            code_pref_or_mesh1 = code_mesh
        self.record["url"] = jpDataUtils.replaceCodes(
            self.record["url"],
            code_map=self.record["code_map"],
            code_pref_or_mesh1=code_pref_or_mesh1,
            year=self.record["year"],
        )
        self.record["zip"] = jpDataUtils.replaceCodes(
            self.record["zip"],
            code_map=self.record["code_map"],
            code_pref_or_mesh1=code_pref_or_mesh1,
            year=self.record["year"],
        )
        self.record["zip_fullpath"] = posixpath.join(self.record["download_fullpath"], self.record["zip"] )
        self.record["shp"] = jpDataUtils.replaceCodes(
            self.record["shp"],
            code_map=self.record["code_map"],
            code_pref_or_mesh1=code_pref_or_mesh1,
            year=self.record["year"],
        )
        self.record["shp_fullpath"] = posixpath.join(self.record["download_fullpath"], self.record["shp"] )
        self.record["altdir"] = jpDataUtils.replaceCodes(
            self.record["altdir"],
            code_map=self.record["code_map"],
            code_pref_or_mesh1=code_pref_or_mesh1,
            year=self.record["year"],
        )
        self.record["qml"] = jpDataUtils.replaceCodes(
            self.record["qml"],
            code_map=self.record["code_map"],
            code_pref_or_mesh1=code_pref_or_mesh1,
            year=self.record["year"],
        )
        self.record["encoding"] = (
            "UTF-8" if self.record["encoding"][:3] == "UTF" else "CP932"
        )
        shp_fullpath = jpDataUtils.findShpFile2(
            self.record["download_fullpath"],
            self.record["year"],
            self.record["shp"],
            self.record["altdir"],
            self.record["code_pref"],
            self.record["code_muni"],
            self.record["name_muni"],
        )
        if shp_fullpath is not None:
            self.record["shp_fullpath"] = shp_fullpath

    def _set_record_from_source(self):
        type_muni = self.record["type_muni"]
        for row in self.source:
            if row["year"] == self.record["year"]:

                if type_muni == "single" or type_muni == "all":
                    self._set_record_from_row(row)
                    break
                elif (
                    type_muni == "detail"
                    and row["detail1"] + " " + row["detail2"] == self.record["detail"]
                ):
                    self._set_record_from_row(row)
                    break
                elif (
                    type_muni == "regional" and row["availability"] == "allprefs"
                ) and (
                    self.record["name_pref"] in jpDataUtils.PREF_NAMES["j"].values()
                    or self.record["name_pref"] in jpDataUtils.PREF_NAMES["e"].values()
                ):
                    self._set_record_from_row(row)
                    break
                elif (
                    type_muni == "regional"
                    and self.record["name_pref"] == row["availability"]
                ):
                    self._set_record_from_row(row)
                    break
                elif type_muni == "mesh1":
                    self._set_record_from_row(row)
                    break

    def _set_record_from_row(self, row):
        self.record["url"] = row["url"]
        self.record["zip"] = row["zip"]
        self.record["shp"] = row["shp"]
        self.record["altdir"] = (
            row["altdir"] if "altdir" in row else self.record["altdir"]
        )
        self.record["qml"] = row["qml"] if "qml" in row else self.record["qml"]
        self.record["epsg"] = row["epsg"] if "encoding" in row else self.record["epsg"]
        self.record["encoding"] = (
            row["encoding"] if "encoding" in row else self.record["encoding"]
        )

    def get_record(self):
        return self.record

    def get_prev_name(self):
        return self.prev_name

    def get_records(self):
        return self.records

    def get_years(self, name_map, name_pref=None, csvfile=None):
        years = []
        csvfile = self.records[name_map].get("year", "")
        if csvfile.isdigit():
            years.append(csvfile)
            return years

        self._load_source(name_map)
        type_muni = self.records[name_map].get("type_muni", "")
        if name_pref is None:
            for row in self.source:
                years.append(row["year"])
        elif name_pref.replace("県", "") == "沖縄":
            for row in self.source:
                if 1971 < int(row["year"]) and (
                    row["availability"] == name_pref
                    or (type_muni != "regional" and type_muni != "detail")
                ):
                    years.append(row["year"])
        else:
            for row in self.source:
                if row["availability"] == name_pref or (
                    type_muni != "regional" and type_muni != "detail"
                ):
                    years.append(row["year"])
        return jpDataUtils.unique_list(years)

    def get_prefs(self, name_map):
        prefs_or_regions = []
        csvfile = self.records[name_map].get("year", "")
        if csvfile.isdigit():
            type_muni = self.records[name_map].get("type_muni", "")
            if type_muni == "" or type_muni == "mesh1":
                for code_pref in range(1, 48):
                    prefs_or_regions.append(
                        jpDataUtils.getPrefNameByCode(code_pref, self.settings.lang1)
                    )
                return prefs_or_regions
            elif type_muni == "single":
                prefs_or_regions.append(TR.NATIONWIDE())
                return prefs_or_regions
        self._load_source(name_map)
        _allprefs = False
        for row in self.source:
            if row["availability"] == "allprefs":
                if _allprefs is False:
                    _allprefs = True
                    for code_pref in range(1, 48):
                        prefs_or_regions.append(
                            jpDataUtils.getPrefNameByCode(
                                code_pref, self.settings.lang1
                            )
                        )
            else:
                prefs_or_regions.append(row["availability"])
        return jpDataUtils.unique_list(prefs_or_regions)

    def get_details(self, name_map, year, name_pref):
        if self.records[name_map]["type_muni"] != "detail":
            return
        details = []
        self._load_source(name_map)
        for row in self.source:
            if row["year"] == year and row["availability"] == name_pref:
                details.append(row["detail1"] + " " + row["detail2"])
        return jpDataUtils.unique_list(details)

    def get_source(self, name_map=None):
        if name_map is not None:
            self._load_source(name_map)
        return self.source

    def _load_source(self, name_map):
        if name_map is None or self.current_source_name == name_map:
            return
        csv_full_path = ""
        csvfile = self.records[name_map].get("year", "")
        if csvfile.isdigit():
            return
        if csvfile.upper()[-4:] == ".CSV":
            csv_full_path = posixpath.join(os.path.dirname(__file__), "csv", csvfile)
        if not os.path.exists(csv_full_path):
            jpDataUtils.printLog(
                "jpdata_lni._load_source: Cannot find the CSV file for "
                + name_map
                + " "
                + csvfile,
            )
        else:
            self.source = jpDataUtils.get_records_from_csv(csv_full_path)
            self.current_source_name = name_map
