from __future__ import absolute_import, division, print_function

from builtins import (bytes, str, open, super, range,
                      zip, round, input, int, pow, object, map, zip)

__author__ = "Andrea Tramacere"

import  numpy  as np

from astropy import wcs

from bokeh.layouts import row, widgetbox,gridplot
from bokeh.models import CustomJS, Slider,HoverTool,ColorBar,LinearColorMapper,LabelSet,ColumnDataSource
from bokeh.embed import components
from bokeh.plotting import figure
from bokeh.palettes import Plasma256



class Image(object):

    def __init__(self,data,header):
        self.data=data
        self.header=header

    def change_image_contrast(self, attr, old, new):
        # print attr,old,new
        self.fig_im.glyph.color_mapper.update(low=self.graph_min_slider.value, high=self.graph_max_slider.value)



    def get_html_draw(self,w=None,h=None, catalog=None, plot=False, vmin=None, vmax=None):

        #import plotly
        #import plotly.graph_objs as go
        #from plotly.graph_objs import  Layout

        # print('vmin,vmax',vmin,vmax)





        msk = ~np.isnan(self.data)
        if vmin is None:
            vmin = self.data[msk].min()

        if vmax is None:
            vmax = self.data[msk].max()

        min_s = self.data.min()
        max_s = self.data.max()
        r = self.data.shape[0] * 2
        c = self.data.shape[1] * 2



        fig = figure(plot_width=w, plot_height=h, x_range=(0, c * 0.5), y_range=(0, r * 0.5),
                     tools=['pan,box_zoom,box_select,wheel_zoom,reset,save,crosshair'])

        w = wcs.WCS(self.header)
        color_mapper = LinearColorMapper(low=min_s, high=max_s, palette=Plasma256)

        fig_im = fig.image(image=[self.data], x=[0], y=[0], dw=[c * 0.5], dh=[r * 0.5],
                           color_mapper=color_mapper)

        hover = HoverTool(tooltips=[("x", "$x"), ("y", "$y"), ("value", "@image")],
                          renderers=[fig_im])

        fig.add_tools(hover)

        #fig, (ax) = plt.subplots(1, 1, figsize=(4, 3), subplot_kw={'projection': WCS(self.header)})
        #im = ax.imshow(self.data,
        #               origin='lower',
        #               zorder=1,
        #               interpolation='none',
        #               aspect='equal',
        #               cmap=plt.get_cmap('jet'),
        #               vmin=vmin,
        #               vmax=vmax)

        if catalog is not None:

            lon = catalog.ra
            lat = catalog.dec


            if len(lat) > 0.:
                pixcrd = w.wcs_world2pix(np.column_stack((lon, lat)), 0)

                msk = ~np.isnan(pixcrd[:, 0])
                #ax.plot(pixcrd[:, 0][msk], pixcrd[:, 1][msk], 'o', mfc='none')
                source = ColumnDataSource(data=dict(lon=pixcrd[:, 0][msk]+0.5,
                                                    lat=pixcrd[:, 1][msk]+0.5,
                                                    names=catalog.name[msk]))
                #for ID, (x, y) in enumerate(pixcrd):
                #    if msk[ID]:
                #        # print ('xy',(pixcrd[:, 0][ID], pixcrd[:, 1][ID]))
                #        ax.annotate('%s' % catalog.name[ID], xy=(x, y), color='white')
                #print(pixcrd[:][msk])
                fig.scatter(x='lon', y='lat', marker='circle', size=15,
                            line_color="white", fill_color=None, alpha=1.0, source=source)

                labels = LabelSet(x='lon', y='lat', text='names', level='glyph',
                                  x_offset=5, y_offset=5, render_mode='canvas', source=source, text_color='white')

                fig.add_layout(labels)
                #print'cat', catalog[msk]


        color_bar = ColorBar(color_mapper=color_mapper,
                             label_standoff=12, border_line_color=None, location=(0, 0))

        JS_code_slider = """
                   var vmin = low_slider.value;
                   var vmax = high_slider.value;
                   fig_im.glyph.color_mapper.high = vmax;
                   fig_im.glyph.color_mapper.low = vmin;
               """


        callback = CustomJS(args=dict(fig_im=fig_im), code=JS_code_slider)

        self.graph_min_slider = Slider(title="Sig. Min", start=min_s, end=max_s, step=1, value=min_s, callback=callback)
        self.graph_max_slider = Slider(title="Sig. Max", start=min_s, end=max_s, step=1, value=max_s * 0.8,
                                  callback=callback)


        self.graph_min_slider.on_change('value', self.change_image_contrast)
        self.graph_max_slider.on_change('value', self.change_image_contrast)

        callback.args["low_slider"] = self.graph_min_slider
        callback.args["high_slider"] = self.graph_max_slider

        #ax.set_xlabel('RA')
        #ax.set_ylabel('DEC')
        #ax.grid(True, color='white')
        #fig.colorbar(im, ax=ax)

        #plugins.connect(fig, plugins.MousePosition(fontsize=14))
        #if plot == True:
        #    print('plot', plot)
        #    mpld3.show()


        fig.add_layout(color_bar, 'right')

        layout = row(
            fig, widgetbox(self.graph_min_slider, self.graph_max_slider),
        )

        #curdoc().add_root(layout)

        #output_file("slider.html", title="slider.py example")
        #from bokeh.io import  show
        #show(layout)

        script, div = components(layout)

        html_dict = {}
        html_dict['script'] = script
        html_dict['div'] = div
        return html_dict



class ScatterPlot(object):


    def __init__(self,w,h,x_label=None,y_label=None,x_range=None,y_range=None,title=None,y_axis_type='linear',x_axis_type='linear'):
        hover = HoverTool(tooltips=[("x", "$x"), ("y", "$y")])

        self.fig = figure(title=title, width=w, height=h,x_range=x_range,y_range=y_range,
                          y_axis_type=y_axis_type,
                          x_axis_type=x_axis_type,
                     tools=[hover, 'pan,box_zoom,box_select,wheel_zoom,reset,save,crosshair']
                     )

        if x_label is not None:
            self.fig.xaxis.axis_label = x_label

        if y_label is not None:
            self.fig.yaxis.axis_label = y_label

    def add_errorbar(self, x, y, xerr=None, yerr=None, color='red',
                 point_kwargs={}, error_kwargs={}):

        self.fig.circle(x, y, color=color, **point_kwargs)

        if xerr is not None:
            x_err_x = []
            x_err_y = []
            for px, py, err in zip(x, y, xerr):
                x_err_x.append((px - err, px + err))
                x_err_y.append((py, py))
            self.fig.multi_line(x_err_x, x_err_y, color=color, **error_kwargs)

        if yerr is not None:
            y_err_x = []
            y_err_y = []
            for px, py, err in zip(x, y, yerr):
                y_err_x.append((px, px))
                y_err_y.append((py - err, py + err))
            self.fig.multi_line(y_err_x, y_err_y, color=color, **error_kwargs)



    def add_step_line(self,x,y,legend=None):
        #print('a')
        self.fig.step(x,y,name=legend, mode="center")
        #print('b')

    def add_line(self,x,y,legend=None,color=None):
        self.fig.line(x,y,legend=legend,line_color=color)

    def get_html_draw(self):



        layout = row(
            self.fig
        )
        #curdoc().add_root(layout)


        #show(layout)

        script, div = components(layout)

        #print ('script',script)
        #print ('div',div)

        html_dict = {}
        html_dict['script'] = script
        html_dict['div'] = div
        return html_dict


class GridPlot(object):

    def __init__(self,f1,f2,w=None,h=None):

        self.f1=f1
        self.f2=f2

    def get_html_draw(self,w=None,h=None):
        #l = layout([self.f1.fig],[self.f2.fig])


        grid = gridplot([self.f1.fig,self.f2.fig],ncols=1,plot_width=w, plot_height=h)
        #curdoc().add_root(grid)
        #show(grid)
        #output_file("test.html")
        script, div = components(grid)

        html_dict={}
        html_dict['script']=script
        html_dict['div'] = div
        return html_dict

[(58, 'bokeh.plotting.figure', 'figure', ([], {'plot_width': 'w', 'plot_height': 'h', 'x_range': '(0, c * 0.5)', 'y_range': '(0, r * 0.5)', 'tools': "['pan,box_zoom,box_select,wheel_zoom,reset,save,crosshair']"}), False, 'from bokeh.plotting import figure\n'), (61, 'astropy.wcs.WCS', 'wcs.WCS', (['self.header'], {}), False, 'from astropy import wcs\n'), (62, 'bokeh.models.LinearColorMapper', 'LinearColorMapper', ([], {'low': 'min_s', 'high': 'max_s', 'palette': 'Plasma256'}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (67, 'bokeh.models.HoverTool', 'HoverTool', ([], {'tooltips': "[('x', '$x'), ('y', '$y'), ('value', '@image')]", 'renderers': '[fig_im]'}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (111, 'bokeh.models.ColorBar', 'ColorBar', ([], {'color_mapper': 'color_mapper', 'label_standoff': '(12)', 'border_line_color': 'None', 'location': '(0, 0)'}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (124, 'bokeh.models.Slider', 'Slider', ([], {'title': '"""Sig. Min"""', 'start': 'min_s', 'end': 'max_s', 'step': '(1)', 'value': 'min_s', 'callback': 'callback'}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (125, 'bokeh.models.Slider', 'Slider', ([], {'title': '"""Sig. Max"""', 'start': 'min_s', 'end': 'max_s', 'step': '(1)', 'value': '(max_s * 0.8)', 'callback': 'callback'}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (158, 'bokeh.embed.components', 'components', (['layout'], {}), False, 'from bokeh.embed import components\n'), (171, 'bokeh.models.HoverTool', 'HoverTool', ([], {'tooltips': "[('x', '$x'), ('y', '$y')]"}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (173, 'bokeh.plotting.figure', 'figure', ([], {'title': 'title', 'width': 'w', 'height': 'h', 'x_range': 'x_range', 'y_range': 'y_range', 'y_axis_type': 'y_axis_type', 'x_axis_type': 'x_axis_type', 'tools': "[hover, 'pan,box_zoom,box_select,wheel_zoom,reset,save,crosshair']"}), False, 'from bokeh.plotting import figure\n'), (220, 'bokeh.layouts.row', 'row', (['self.fig'], {}), False, 'from bokeh.layouts import row, widgetbox, gridplot\n'), (228, 'bokeh.embed.components', 'components', (['layout'], {}), False, 'from bokeh.embed import components\n'), (250, 'bokeh.layouts.gridplot', 'gridplot', (['[self.f1.fig, self.f2.fig]'], {'ncols': '(1)', 'plot_width': 'w', 'plot_height': 'h'}), False, 'from bokeh.layouts import row, widgetbox, gridplot\n'), (254, 'bokeh.embed.components', 'components', (['grid'], {}), False, 'from bokeh.embed import components\n'), (44, 'numpy.isnan', 'np.isnan', (['self.data'], {}), True, 'import numpy as np\n'), (149, 'bokeh.layouts.widgetbox', 'widgetbox', (['self.graph_min_slider', 'self.graph_max_slider'], {}), False, 'from bokeh.layouts import row, widgetbox, gridplot\n'), (193, 'builtins.zip', 'zip', (['x', 'y', 'xerr'], {}), False, 'from builtins import bytes, str, open, super, range, zip, round, input, int, pow, object, map, zip\n'), (201, 'builtins.zip', 'zip', (['x', 'y', 'yerr'], {}), False, 'from builtins import bytes, str, open, super, range, zip, round, input, int, pow, object, map, zip\n'), (104, 'bokeh.models.LabelSet', 'LabelSet', ([], {'x': '"""lon"""', 'y': '"""lat"""', 'text': '"""names"""', 'level': '"""glyph"""', 'x_offset': '(5)', 'y_offset': '(5)', 'render_mode': '"""canvas"""', 'source': 'source', 'text_color': '"""white"""'}), False, 'from bokeh.models import CustomJS, Slider, HoverTool, ColorBar, LinearColorMapper, LabelSet, ColumnDataSource\n'), (89, 'numpy.column_stack', 'np.column_stack', (['(lon, lat)'], {}), True, 'import numpy as np\n'), (91, 'numpy.isnan', 'np.isnan', (['pixcrd[:, (0)]'], {}), True, 'import numpy as np\n')]