# -*- coding: utf-8 -*-
# Copyright (c) 2015, Vispy Development Team.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.

from __future__ import division

from .image import ImageVisual
from ..color import Color
from .shaders import Function


grid_color = """
vec4 grid_color(vec2 pos) {
    vec4 px_pos = $map_to_doc(vec4(pos, 0, 1));
    px_pos /= px_pos.w;

    // Compute vectors representing width, height of pixel in local coords
    float s = 1.;
    vec4 local_pos = $map_doc_to_local(px_pos);
    vec4 dx = $map_doc_to_local(px_pos + vec4(1.0 / s, 0, 0, 0));
    vec4 dy = $map_doc_to_local(px_pos + vec4(0, 1.0 / s, 0, 0));
    local_pos /= local_pos.w;
    dx = dx / dx.w - local_pos;
    dy = dy / dy.w - local_pos;

    // Pixel length along each axis, rounded to the nearest power of 10
    vec2 px = s * vec2(abs(dx.x) + abs(dy.x), abs(dx.y) + abs(dy.y));
    float log10 = log(10.0);
    float sx = pow(10.0, floor(log(px.x) / log10)+1) * $scale.x;
    float sy = pow(10.0, floor(log(px.y) / log10)+1) * $scale.y;

    float max_alpha = 0.6;
    float x_alpha = 0.0;

    if (mod(local_pos.x, 1000 * sx) < px.x) {
        x_alpha = clamp(1 * sx/px.x, 0, max_alpha);
    }
    else if (mod(local_pos.x, 100 * sx) < px.x) {
        x_alpha = clamp(.1 * sx/px.x, 0, max_alpha);
    }
    else if (mod(local_pos.x, 10 * sx) < px.x) {
        x_alpha = clamp(0.01 * sx/px.x, 0, max_alpha);
    }

    float y_alpha = 0.0;
    if (mod(local_pos.y, 1000 * sy) < px.y) {
        y_alpha = clamp(1 * sy/px.y, 0, max_alpha);
    }
    else if (mod(local_pos.y, 100 * sy) < px.y) {
        y_alpha = clamp(.1 * sy/px.y, 0, max_alpha);
    }
    else if (mod(local_pos.y, 10 * sy) < px.y) {
        y_alpha = clamp(0.01 * sy/px.y, 0, max_alpha);
    }

    float alpha = (((log(max(x_alpha, y_alpha))/log(10.))+2) / 3);
    if (alpha == 0) {
        discard;
    }
    return vec4($color.rgb, $color.a * alpha);
}
"""


class GridLinesVisual(ImageVisual):
    """ Displays regularly spaced grid lines in any coordinate system and at
    any scale.

    Parameters
    ----------
    scale : tuple
        The scale factors to apply when determining the spacing of grid lines.
    color : Color
        The base color for grid lines. The final color may have its alpha
        channel modified.
    """
    def __init__(self, scale=(1, 1), color='w'):
        # todo: PlaneVisual should support subdivide/impostor methods from
        # image and gridlines should inherit from plane instead.
        self._grid_color_fn = Function(grid_color)
        self._grid_color_fn['color'] = Color(color).rgba
        self._grid_color_fn['scale'] = scale
        ImageVisual.__init__(self, method='impostor')
        self.set_gl_state('additive', cull_face=False)
        self.shared_program.frag['get_data'] = self._grid_color_fn
        cfun = Function('vec4 null(vec4 x) { return x; }')
        self.shared_program.frag['color_transform'] = cfun

    @property
    def size(self):
        return (1, 1)

    def _prepare_transforms(self, view):
        fn = self._grid_color_fn
        fn['map_to_doc'] = self.get_transform('visual', 'document')
        fn['map_doc_to_local'] = self.get_transform('document', 'visual')
        ImageVisual._prepare_transforms(self, view)

    def _prepare_draw(self, view):
        if self._need_vertex_update:
            self._build_vertex_data()
            
        if view._need_method_update:
            self._update_method(view)
