# filename: formats/topstation_jsi.py
# Copyright 2022 Jean-Marie Arsac <jmarsac@azimut.fr>

# This file is part of Total Open Station.

# Total Open Station is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.

# Total Open Station is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with Total Open Station.  If not, see
# <http://www.gnu.org/licenses/>.

import logging
import re

from ...ptopo import Ptopo, PtopoConst
from . import UNKNOWN_POINT, Feature, Parser, Point

# Exemple de contenu traité :
# S.50570:X=1352312.6096,Y=7222488.3463,Z=26.105,PH=7,PV=7,CS=1,MD=P_STATION,CA=TOPSTA
# S.50571:X=1352270.3770,Y=7222495.1687,PH=7,CS=1,MD=P_STATION,CA=TOPSTA
# S.25687:X=1352339.5100,Y=7222586.0400,Z=26.16400,PH=7,PV=7,MD=P_STATION,CA=TOPSTA
# S.16836:X=1352368.5072,Y=7222455.6587,Z=26.20650,PH=7,PV=7,CS=1,MD=P_STATION,CA=TOPSTA

logger = logging.getLogger(__name__)


def precision(pvph):
    if pvph > 5:
        return "A"
    else:
        return "B"


class TopstationJsiConst:
    STATION = "S"
    INSTRUMENT_HEIGHT = "HI"
    CODE = "C"
    CODE_SYMBOLE = "CS"
    MATRICULE = "M"
    M_DESCRIPTION = "MD"
    TARGET_HEIGHT = "HV"
    HORIZONTAL_ANGLE = "AH"
    VERTICAL_ANGLE = "AV"
    SLOPE_DISTANCE = "DI"
    VERTICAL_DISTANCE = "DZ"
    HORIZONTAL_DISTANCE = "DH"
    NORTH = "Y"
    EAST = "X"
    ALTITUDE = "Z"
    PRECISION_PLANI = "PH"
    PRECISION_ALTI = "PV"


class FormatParser(Parser):
    def __init__(self, data, **options):
        self._use_all = False
        self._ptopo_only = False
        if "ptopo_only" in options:
            self._ptopo_only = options["ptopo_only"]

        lines = data.splitlines()
        self.tdict = []
        for line in lines:
            if not self._ptopo_only or ("X=" in line and ",Y=" in line):
                row = {}
                try:
                    fields = re.split("[:,]", line)
                    for field in fields:
                        key_value = field.split("=")
                        l = len(key_value)
                        if l == 1:
                            row[TopstationJsiConst.MATRICULE] = key_value[0]
                        elif l == 2:
                            row[key_value[0]] = key_value[1]
                except Exception as e:
                    logger.debug(f"{line}\n{str(e)}")
                else:
                    if len(row):
                        self.tdict.append(row)

    def is_point(self, row):
        is_point = False
        if (
            TopstationJsiConst.MATRICULE in row
            and TopstationJsiConst.EAST in row
            and TopstationJsiConst.NORTH in row
        ):
            is_point = True
        return is_point

    def extract_point(self, row):
        p = UNKNOWN_POINT
        x = float(row[TopstationJsiConst.EAST])
        y = float(row[TopstationJsiConst.NORTH])
        if TopstationJsiConst.ALTITUDE in row:
            z = float(row[TopstationJsiConst.ALTITUDE])
        else:
            z = PtopoConst.NO_Z
        p = Point(x, y, z)
        return p

    def get_point(self, row):
        f = None
        p = self.extract_point(row)
        point_type = "P"
        if TopstationJsiConst.MATRICULE in row:
            point_name = row[TopstationJsiConst.MATRICULE]
        if TopstationJsiConst.M_DESCRIPTION in row:
            if row[TopstationJsiConst.M_DESCRIPTION] == "P_STATION":
                point_type = "S"
        ph = pv = 1
        c = None
        if TopstationJsiConst.PRECISION_PLANI in row:
            ph = int(row[TopstationJsiConst.PRECISION_PLANI])
        if TopstationJsiConst.PRECISION_ALTI in row:
            pv = int(row[TopstationJsiConst.PRECISION_ALTI])
        if TopstationJsiConst.CODE in row:
            c = row[TopstationJsiConst.CODE]
        f = Feature(
            p,
            desc=point_type,
            id=point_name,
            point_name=point_name,
            prec_xy=precision(ph),
            prec_z=precision(pv),
            code=c,
        )
        return f

    def split_points(self):
        pass
        return None

    @property
    def raw_line(self):
        """Extract all Topstation Jsi data."""
        points = []
        idx = 0
        for row in self.tdict:
            idx = idx + 1
            if self.is_point(row):
                f = self.get_point(row)
                points.append(f)
        logger.debug(points)
        return points
