# -*- coding: utf-8 -*-

import re

from outwiker.api.core.attachment import Attachment

from .graphelements import Graph, Curve
from .datasources import StringSource, FileSource
from . import defines


class GraphBuilder:
    """Class for creation Graph and fill its properties"""

    def __init__(self, params_dict, content, page):
        """
        params_dict - dictionary with parameters of the(:plot:) command
        content - text between (:plot:) and (:plotend:)
        page - wiki page for that will create graph
        """
        self._graph = Graph()
        self._build(params_dict, page, content)

    def _build(self, params_dict, page, content):
        curvenames = self._createCurves(params_dict)
        self._setUpProperties(params_dict)
        self._setDataSources(curvenames, page, content)

    def _setUpProperties(self, params_dict):
        """Set-up properties of the inner objects"""
        self._sep = "."

        for key, val in params_dict.items():
            if key.endswith(self._sep):
                key = key[:-1]

            self._setObjectProperties(self.graph, key, val)

    def _setObjectProperties(self, obj, key, val):
        """Set properties for single object and them children"""
        splitted = [
            subkey.lower() for subkey in key.split(self._sep, 1) if len(subkey) != 0
        ]
        if len(splitted) == 1:
            obj.setProperty(splitted[0], val)
        else:
            subobject = obj.getObject(splitted[0])
            if subobject is not None:
                self._setObjectProperties(subobject, splitted[1], val)

    def _createCurves(self, params_dict):
        """Create curves by parameters.
        Return set of the names of the new curves"""

        curvename = re.compile(r"^(?P<name>curve\d*)\.", re.IGNORECASE)
        names = set(["curve"])

        for key in params_dict:
            match = curvename.match(key)
            if match is not None:
                names.update(match.groups("name"))

        for name in names:
            self._graph.addObject(name.lower(), Curve())

        return names

    def _setDataSources(self, curvenames, page, content):
        """
        Set data sources (StringSource or FileSource) for all curves
        """
        for name in curvenames:
            curve = self._graph.getObject(name)
            assert curve is not None

            data = curve.getObject(defines.CURVE_DATA_OBJECT_NAME)
            assert data is not None

            colsep = data.getProperty(
                defines.DATA_COLUMNS_SEPARATOR_NAME,
                defines.DATA_COLUMNS_SEPARATOR_DEFAULT,
            )

            try:
                skiprows = int(data.getProperty(defines.DATA_SKIP_ROWS_NAME, "0"))
            except ValueError:
                skiprows = 0

            attachName = curve.getProperty(defines.CURVE_DATA_NAME, None)
            if attachName is None:
                data.setSource(
                    StringSource(content.strip(), colsep=colsep, skiprows=skiprows)
                )
            else:
                # Remove prefix "Attach:"
                attachPrefix = "Attach:"
                if attachName.startswith(attachPrefix):
                    attachName = attachName[len(attachPrefix) :]

                # Get full path to the attached file
                path = Attachment(page).getFullPath(attachName)
                data.setSource(FileSource(path, colsep=colsep, skiprows=skiprows))

    @property
    def graph(self):
        return self._graph
