"""
/***************************************************************************
 SeilaplanPlugin
                                 A QGIS plugin
 Seillinien-Layoutplaner
                              -------------------
        begin                : 2013
        copyright            : (C) 2015 by ETH Zürich
        email                : seilaplanplugin@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import csv

import numpy as np

from SEILAPLAN.tools.height_source import AbstractSurveyReader


class CsvXyzReader(AbstractSurveyReader):

    def __init__(self, path):
        AbstractSurveyReader.__init__(self, path)

        self.sep = None
        self.idxX = None
        self.idxY = None
        self.idxZ = None

        self.checkStructure()

    def checkStructure(self):

        with open(self.path, newline="") as file:
            reader = csv.reader(file)
            sep = ","
            for row in reader:
                if len(row) == 1:
                    row = row[0].split(";")
                    sep = ";"
                if len(row) == 1:
                    row = row[0].split(",")
                    sep = ","

                # Analyse header line
                idxX = [idx for idx, h in enumerate(row) if self.formatHeader(h) == "X"]
                idxY = [idx for idx, h in enumerate(row) if self.formatHeader(h) == "Y"]
                idxZ = [idx for idx, h in enumerate(row) if self.formatHeader(h) == "Z"]
                break

        # Check if data is in x, y, z format
        if len(idxX) == 1 and len(idxY) == 1 and len(idxZ) == 1:
            self.sep = sep
            self.idxX = idxX[0]
            self.idxY = idxY[0]
            self.idxZ = idxZ[0]
            self.valid = True

    def readOutData(self):
        if not self.valid:
            return False
        try:
            x, y, z = np.genfromtxt(
                self.path,
                delimiter=self.sep,
                dtype="float64",
                usecols=(self.idxX, self.idxY, self.idxZ),
                unpack=True,
                skip_header=1,
            )
        except TypeError:
            return False
        if isinstance(x, float) or isinstance(y, float) or isinstance(z, float):
            return False
        # Check for missing values and remove whole row
        x = x[~(np.isnan(x) + np.isnan(y) + np.isnan(z))]
        y = y[~(np.isnan(x) + np.isnan(y) + np.isnan(z))]
        z = z[~(np.isnan(x) + np.isnan(y) + np.isnan(z))]

        # Are there enough points?
        if len(x) < 2:
            return False

        self.surveyPoints = {"x": x, "y": y, "z": z}
        self.nr = np.arange(len(x)) + 1
        return True
