# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012-2016 Kozea
#
# This library is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This library 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.


"""
Solid Guage
For each series a solid guage is shown on the plot area.
"""
from __future__ import division

from math import pi, sqrt

from pygal.graph.graph import Graph
from pygal.util import alter, decorate


class SolidGauge(Graph):

    def gaugify(self, serie, squares, sq_dimensions, current_square):
        serie_node = self.svg.serie(serie)
        if self.half_pie:
            start_angle = 3 * pi / 2
            center = (
                (current_square[1] * sq_dimensions[0]) - (
                    sq_dimensions[0] / 2.),
                (current_square[0] * sq_dimensions[1]) - (
                    sq_dimensions[1] / 4))
            end_angle = pi / 2
        else:
            start_angle = 0
            center = (
                (current_square[1] * sq_dimensions[0]) - (
                    sq_dimensions[0] / 2.),
                (current_square[0] * sq_dimensions[1]) - (
                    sq_dimensions[1] / 2.))
            end_angle = 2 * pi

        max_value = serie.metadata.get(0, {}).get('max_value', 100)
        radius = min([sq_dimensions[0] / 2, sq_dimensions[1] / 2]) * .9
        small_radius = radius * serie.inner_radius

        self.svg.gauge_background(
            serie_node, start_angle, center, radius, small_radius, end_angle,
            self.half_pie, self._serie_format(serie, max_value))

        sum_ = 0
        for i, value in enumerate(serie.values):
            if value is None:
                continue
            ratio = min(value, max_value) / max_value
            if self.half_pie:
                angle = 2 * pi * ratio / 2
            else:
                angle = 2 * pi * ratio

            val = self._format(serie, i)
            metadata = serie.metadata.get(i)

            gauge_ = decorate(
                self.svg,
                self.svg.node(serie_node['plot'], class_="gauge"),
                metadata)

            alter(
                self.svg.solid_gauge(
                    serie_node, gauge_, radius, small_radius,
                    angle, start_angle, center, val, i, metadata,
                    self.half_pie, end_angle,
                    self._serie_format(serie, max_value)),
                metadata)
            start_angle += angle
            sum_ += value

        x, y = center
        self.svg.node(
            serie_node['text_overlay'], 'text',
            class_='value gauge-sum',
            x=x,
            y=y + self.style.value_font_size / 3,
            attrib={'text-anchor': 'middle'}
        ).text = self._serie_format(serie, sum_)

    def _compute_x_labels(self):
        pass

    def _compute_y_labels(self):
        pass

    def _plot(self):
        """Draw all the serie slices"""
        squares = self._squares()
        sq_dimensions = self.add_squares(squares)

        for index, serie in enumerate(self.series):
            current_square = self._current_square(squares, index)
            self.gaugify(
                serie, squares, sq_dimensions, current_square)

    def _squares(self):

        n_series_ = len(self.series)
        i = 2

        if sqrt(n_series_).is_integer():
            _x = int(sqrt(n_series_))
            _y = int(sqrt(n_series_))
        else:
            while i * i < n_series_:
                while n_series_ % i == 0:
                    n_series_ = n_series_ / i
                i = i + 1
            _y = int(n_series_)
            _x = int(len(self.series) / _y)
            if len(self.series) == 5:
                _x, _y = 2, 3
            if abs(_x - _y) > 2:
                _sq = 3
                while (_x * _y) - 1 < len(self.series):
                    _x, _y = _sq, _sq
                    _sq += 1
        return (_x, _y)

    def _current_square(self, squares, index):
        current_square = [1, 1]
        steps = index + 1
        steps_taken = 0
        for i in range(squares[0] * squares[1]):
            steps_taken += 1
            if steps_taken != steps and steps_taken % squares[0] != 0:
                current_square[1] += 1
            elif steps_taken != steps and steps_taken % squares[0] == 0:
                current_square[1] = 1
                current_square[0] += 1
            else:
                return tuple(current_square)
        raise Exception(
            'Something went wrong with the current square assignment.')
