# -*- coding: utf-8 -*-
"""
/***************************************************************************
 xmlToPython
                                 A QGIS plugin
 This module convert a specific Gaphab XML file into a Python object. It use declxml.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2020-04-20
        git sha              : $Format:%H$
        copyright            : (C) 2020 by ThéMA
        email                : robin.marlinl@gmail.com
        author               : Robin Marlin-Lefebvre
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

from .declxml import *
import re


class Projet:

    def __init__(self):
        self.name = None
        self.codes = []
        self.patchCodes = []
        self.noData = None
        self.con8 = None
        self.minArea = None
        self.simplify = None
        self.capacityParams = []
        self.resolution = None
        self.grid2space = []
        self.space2grid = []
        self.costLinks = []
        self.exoDatas = []
        self.graphs = []
        self.zone = []
        self.demFile = None
        self.wktCRS = None

    def __repr__(self):
        return '\nProjet(name={}, codes={}, patchCodes={}, noData={}, con8={}, minArea={}, simplify={}, ' \
               '\ncapacityParams={}, resolution={}, \ngrid2space={}, \nspace2grid={}, \ncostLinks={}, \nexoDatas={},' \
               '\ngraphs={}, ' \
               '\nzone={}, ' \
               '\ndemFile={}' \
               '\nwktCRS={})'.format(self.name, self.codes, self.patchCodes, self.noData, self.con8, self.minArea,
                                     self.simplify, self.capacityParams, self.resolution, self.grid2space,
                                     self.space2grid, self.costLinks, self.exoDatas, self.graphs, self.zone,
                                     self.demFile, self.wktCRS)


class CapacityParam:
    def __init__(self):
        self.calcArea = None
        self.maxCost = None
        self.weightCost = None

    def __repr__(self):
        return '\nCapacityParam(calcArea={}, maxCost={}, weightCost={})'.format(self.calcArea,
                                                                                self.maxCost, self.weightCost)


class Grid2space:
    def __init__(self):
        self.m00 = None
        self.m01 = None
        self.m02 = None
        self.m10 = None
        self.m11 = None
        self.m12 = None

    def __repr__(self):
        return '\nGrid2space(m00={}, m01={}, m02={}, m10={}, m11={}, m12={})'.format(self.m00, self.m01, self.m02,
                                                                                     self.m10, self.m11, self.m12)


class Space2grid:
    def __init__(self):
        self.m00 = None
        self.m01 = None
        self.m02 = None
        self.m10 = None
        self.m11 = None
        self.m12 = None

    def __repr__(self):
        return '\nSpace2grid(m00={}, m01={}, m02={}, m10={}, m11={}, m12={})'.format(self.m00, self.m01, self.m02,
                                                                                     self.m10, self.m11, self.m12)


class Linkset:
    def __init__(self):
        self.name = None
        self.type = None
        self.type__dist = None
        self.type__length = None
        self.costs = []
        self.realPaths = None
        self.removeCrossPatch = None
        self.coefSlope = None
        self.distMax = None
        self.extCostFile = None
        self.optimCirc = None

    def __repr__(self):
        return '\nLinkset(name={}, type={}, type__dist={}, type__length={}, costs={}, realPaths={}, ' \
               'removeCrossPatch={}, coefSlope={}, distMax={}, extCostFile={}, ' \
               'optimCirc={})'.format(self.name, self.type, self.type__dist, self.type__length, self.costs,
                                      self.realPaths, self.removeCrossPatch, self.coefSlope, self.distMax,
                                      self.extCostFile, self.optimCirc)


class Pointset:
    def __init__(self):
        self.name = None
        self.costLink = None
        self.maxCost = None
        self.agregType = None

    def __repr__(self):
        return '\nPointset(name={}, cost={}, maxCost={}, \nagregType={})'.format(self.name, self.cost, self.maxCost,
                                                                                 self.agregType)


class Graph:
    def __init__(self):
        self.name = None
        self.costLink = None
        self.type = None
        self.threshold = None
        self.intraPatchDist = None
        self.saved = None

    def __repr__(self):
        return '\nGraph(name={}, costLink={}, \ntype={}, threshold={}, ' \
               'intraPatchDist={}, saved={})'.format(self.name, self.costLink, self.type,
                                                     self.threshold, self.intraPatchDist, self.saved)


class Zone:
    def __init__(self):
        self.x = None
        self.y = None
        self.width = None
        self.height = None

    def __repr__(self):
        return '\nZone(x={}, y={}, width={}, height={})'.format(self.x, self.y, self.width, self.height)


def liaisonLinksetToGraph(p):
    """Link a Linkset to a Graph by using the Graph xPath"""
    for graph in p.graphs:
        regex = re.compile(r'costLinks\/entry\[(\d+)\]\/Linkset')
        indexLinkset = regex.findall(graph.costLink)
        if len(indexLinkset) < 0 or len(indexLinkset) > 1:
            raise Exception("Problème lors du chargement des jeux de lien.")
        elif len(indexLinkset) == 1:
            graph.costLink = p.costLinks[int(indexLinkset[0]) - 1]
        elif len(indexLinkset) == 0 and len(p.costLinks) > 0:
            graph.costLink = p.costLinks[0]
        else:
            raise Exception("Problème lors du chargement des jeux de lien.")

def liaisonLinksetToPointset(p):
    """Link a Linkset to a Pointset by using the Pointset xPath"""
    for pointset in p.exoDatas:
        regex = re.compile(r'costLinks\/entry\[(\d+)\]\/Linkset')
        indexLinkset = regex.findall(pointset.costLink)
        if len(indexLinkset) < 0 or len(indexLinkset) > 1:
            raise Exception("Problème lors du chargement des jeux de lien.")
        elif len(indexLinkset) == 1:
            pointset.costLink = p.costLinks[int(indexLinkset[0]) - 1]
        elif len(indexLinkset) == 0 and len(p.costLinks) > 0:
            pointset.costLink = p.costLinks[0]
        else:
            raise Exception("Problème lors du chargement des jeux de lien.")

def convertXmlToPy(filepath):
    """Main function to use, translate a XML file into a Graphab project"""
    file = open(filepath)
    xml_string = file.read()
    file.close()

    processor = user_object('Project', Projet, [
        string('name', alias='name'),
        array(integer('int'), alias='codes', nested='codes'),
        array(integer('int'), alias='patchCodes', nested='patchCodes'),
        floating_point('noData', alias='noData'),
        boolean('con8', alias='con8'),
        floating_point('minArea', alias='minArea'),
        boolean('simplify', alias='simplify'),
        user_object('capacityParams', CapacityParam, [
            boolean('calcArea', alias='calcArea'),
            floating_point('maxCost', alias='maxCost'),
            boolean('weightCost', alias='weightCost')
        ], alias='capacityParams'),
        floating_point('resolution', alias='resolution'),
        user_object('grid2space', Grid2space, [
            floating_point('m00', alias='m00'),
            floating_point('m01', alias='m01'),
            floating_point('m02', alias='m02'),
            floating_point('m10', alias='m10'),
            floating_point('m11', alias='m11'),
            floating_point('m12', alias='m12')
        ], alias='grid2space'),
        user_object('space2grid', Space2grid, [
            floating_point('m00', alias='m00'),
            floating_point('m01', alias='m01'),
            floating_point('m02', alias='m02'),
            floating_point('m10', alias='m10'),
            floating_point('m11', alias='m11'),
            floating_point('m12', alias='m12')
        ], alias='space2grid'),
        array(user_object('Linkset', Linkset, [
            string('name', alias='name'),
            integer('type', alias='type'),
            integer('type__dist', alias='type__dist'),
            integer('type__length', alias='type__length'),
            array(floating_point('double', required=False), alias='costs', nested='costs'),
            boolean('realPaths', alias='realPaths'),
            boolean('removeCrossPatch', alias='removeCrossPatch'),
            floating_point('coefSlope', alias='coefSlope', required=False),
            floating_point('distMax', alias='distMax'),
            string('extCostFile', alias='extCostFile', required=False),
            boolean('optimCirc', alias='optimCirc', required=False)
        ], required=False), alias='costLinks', nested="costLinks/entry"),
        array(user_object('Pointset', Pointset, [
            string('name', alias='name'),
            string('cost', attribute='reference', alias='costLink'),
            floating_point('maxCost', alias='maxCost'),
            integer('agregType', alias='agregType')
        ], required=False), alias='exoDatas', nested="exoDatas/entry"),
        array(user_object('Graph', Graph, [
            string('name', alias='name'),
            string('cost', attribute='reference', alias='costLink'),
            integer('type', alias='type'),
            floating_point('threshold', alias='threshold'),
            boolean('intraPatchDist', alias='intraPatchDist'),
            boolean('saved', alias='saved')
        ], required=False), alias='graphs', nested="graphs/entry"),
        array(user_object('zone', Zone, [
            floating_point('x', alias='x'),
            floating_point('y', alias='y'),
            floating_point('width', alias='width'),
            floating_point('height', alias='height')
        ]), alias='zone'),
        string('demFile', alias='demFile', required=False),
        string('wktCRS', alias='wktCRS', required=False)
    ])

    p = parse_from_string(processor, xml_string)

    liaisonLinksetToPointset(p)
    liaisonLinksetToGraph(p)

    return p