# (c) Nelen & Schuurmans.  GPL licensed, see LICENSE.rst.


import logging
import os
from collections import OrderedDict

try:
    from osgeo import ogr
except ImportError:
    ogr = None

from threedigrid.admin import exporter_constants as const
from threedigrid.geo_utils import get_spatial_reference
from threedigrid.numpy_utils import reshape_flat_array
from threedigrid.orm.base.exporters import BaseOgrExporter

logger = logging.getLogger(__name__)


class LeveeOgrExporter(BaseOgrExporter):
    """
    Exports to ogr formats. You need to set the driver explicitly
    before calling save()
    """

    def __init__(self, levees):
        """
        :param lines: lines.models.Lines instance
        """
        self._levees = levees
        self.supported_drivers = {
            const.GEO_PACKAGE_DRIVER_NAME,
            const.SHP_DRIVER_NAME,
            const.GEOJSON_DRIVER_NAME,
        }
        self.driver = None

    def save(self, file_name, levee_data, target_epsg_code, **kwargs):
        """
        save to file format specified by the driver, e.g. shapefile

        :param file_name: name of the outputfile
        :param line_data: dict of line data
        """
        if self.driver is None:
            self.set_driver(extension=os.path.splitext(file_name)[1])

        assert self.driver is not None

        geomtype = 0
        sr = get_spatial_reference(target_epsg_code)

        self.del_datasource(file_name)
        data_source = self.driver.CreateDataSource(file_name)
        layer = data_source.CreateLayer(str(os.path.basename(file_name)), sr, geomtype)
        # accounts for 2D only
        fields = OrderedDict(
            [
                ("id", "int"),
                ("cr_level", "float"),
                ("mx_depth", "float"),
            ]
        )

        for field_name, field_type in fields.items():
            layer.CreateField(
                ogr.FieldDefn(field_name, const.OGR_FIELD_TYPE_MAP[field_type])
            )
        _definition = layer.GetLayerDefn()

        for i in range(len(self._levees.geoms)):
            if levee_data["id"][i] == 0:
                continue  # skip the dummy element
            line = ogr.Geometry(ogr.wkbLineString)
            feature = ogr.Feature(_definition)
            linepoints = reshape_flat_array(levee_data["coords"][i]).T
            for x in linepoints:
                line.AddPoint(x[0], x[1])
            feature.SetGeometry(line)
            # for field_name, field_type in fields.iteritems():
            #     raw_value = levee_data[field_name][i]
            #     print("raw_value  ", raw_value)
            #     value = TYPE_FUNC_MAP[field_type](raw_value)
            #     print("value  ", value)

            self.set_field(feature, "id", "int", levee_data["id"][i])
            self.set_field(feature, "cr_level", "float", levee_data["crest_level"][i])
            self.set_field(
                feature, "mx_depth", "float", levee_data["max_breach_depth"][i]
            )
            layer.CreateFeature(feature)
            feature.Destroy()
