import iplotter
from IPython.core.display import HTML

"""
Explanation: Beautiful JavaScript Charts in Jupyter Notebooks
Jupyter Notebooks tell stories by blending explanations, visualizations, and the code producing them. In my opinion, the most compelling charts are interactive, Javascript based. Here's how you can blend beautiful Javascript charts into Jupyter Notebooks to tell your story. 
For simple, plots iPlotter brings the latest D3.js and canvas charting libraries to Jupyter Notebooks using native python data structures. iPlotter integrates with C3.js, plotly.js, Chart.js, Chartist.js, and Google Charts. 
To get started:
bash
$ pip install iplotter
When this fails, you can directly render JavaScript by passing Python data structures either as strings or through dictionaries as json.
End of explanation
"""


# remove iFrame border for cleaner chart rendering
# increase size of text explanations
HTML("""
<style>
iframe {border:0;}
</style>
""")

"""
Explanation: Before we dive in to the charts, let's adjust the iframe style jupyter notebooks use so charts render more cleanly.
End of explanation
"""


# define chart + data
chart = {
    "data": {
        "columns": [
            ["setosa_x", 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3.0, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3.0, 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3.0, 3.8, 3.2, 3.7, 3.3],
            ["versicolor_x", 3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2.0, 3.0, 2.2, 2.9, 2.9, 3.1, 3.0, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3.0, 2.8, 3.0, 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3.0, 3.4, 3.1, 2.3, 3.0, 2.5, 2.6, 3.0, 2.6, 2.3, 2.7, 3.0, 2.9, 2.9, 2.5, 2.8],
            ["setosa", 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2],
            ["versicolor", 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1.0, 1.3, 1.4, 1.0, 1.5, 1.0, 1.4, 1.3, 1.4, 1.5, 1.0, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1.0, 1.1, 1.0, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1.0, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3]
        ],
     "type": 'scatter'
            },
    "axis": {
        "x": {
            "label": 'Sepal.Width',
            "tick": {
                "fit": "false"
            }
        },
        "y": {
            "label": 'Petal.Width'
        }
    }
}

c3_plotter = iplotter.C3Plotter()
c3_plotter.plot(chart)

"""
Explanation: To use iPlotter, select your JavaScript charting library of choice. Then, pass a python data structure in a format corresponding to the json the library expects. 
C3.js
is a charting library based on D3.js that makes it easy to build and reuse beautiful charts.
End of explanation
"""


chart = {
    "data": {
        "columns": [
            ['dogs', 300, 350, 300, 0, 0, 120],
            ['cats', 130, 100, 140, 200, 150, 50],
            ['people', 180, 75, 265, 100, 50, 100]
        ],
        "types": {
            "dogs": 'area-spline',
            "cats": 'area-spline',
            "people": 'area-spline'
        },
        "groups": [['dogs', 'cats', 'people']]
    }
}


c3_plotter = iplotter.C3Plotter()
c3_plotter.plot(chart)

"""
Explanation: How about line charts?
End of explanation
"""


labels = ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
values = [{"x":20, "y": 30, "r":15}, {"x":40, "y":10, "r":10}]

data = {    
    "labels": labels,
    "datasets": [
        {
            "label": "My First dataset",
            "backgroundColor": "rgba(179,181,198,0.2)",
            "borderColor": "rgba(179,181,198,1)",
            "pointBackgroundColor": "rgba(179,181,198,1)",
            "pointBorderColor": "#fff",
            "pointHoverBackgroundColor": "#fff",
            "pointHoverBorderColor": "rgba(179,181,198,1)",
            "data": [65, 59, 90, 81, 56, 55, 40]
        },
        {
            "label": "My Second dataset",
            "backgroundColor": "rgba(255,99,132,0.2)",
            "borderColor": "rgba(255,99,132,1)",
            "pointBackgroundColor": "rgba(255,99,132,1)",
            "pointBorderColor": "#fff",
            "pointHoverBackgroundColor": "#fff",
            "pointHoverBorderColor": "rgba(255,99,132,1)",
            "data": [28, 48, 40, 19, 96, 27, 100]
        }
    ]
}

chart_js = iplotter.ChartJSPlotter()

chart_js.plot(data, chart_type="radar", w=600, h=600)

"""
Explanation: Chart.js
Chart.js requires a slightly different input format, but works similarly. Chart.js is a canvas charting library so it can handle many points!
End of explanation
"""


data = [
    ['Genre', 'Fantasy & Sci Fi', 'Romance', 'Mystery/Crime', 'General',
     'Western', 'Literature', {"role": 'annotation'}],
    ['2010', 10, 24, 20, 32, 18, 5, ''],
    ['2020', 16, 22, 23, 30, 16, 9, ''],
    ['2030', 28, 19, 29, 30, 12, 13, '']
]

options = {
    "width": 600,
    "height": 400,
    "legend": {"position": 'top', "maxLines": 3},
    "bar": {"groupWidth": '75%'},
    "isStacked": "true",
}

gc_plotter = iplotter.GCPlotter()
gc_plotter.plot(data, chart_type="ColumnChart",chart_package='corechart', options=options)

"""
Explanation: Google Charts
License is  Creative Commons Attribution 3.0 License, which requires attribution, but allows for free commercial/personal use. No data is not sent to a Google server. It's rendered in the browser.
End of explanation
"""


data = [
          ['Task', 'Hours per Day'],
          ['Work',     11],
          ['Eat',      2],
          ['Commute',  2],
          ['Watch TV', 2],
          ['Sleep',    7]
]

options = {
"title": "hi"
}

gc_plotter = iplotter.GCPlotter()
gc_plotter.plot(data, chart_type="piechart", options=options)
# sad face :<

"""
Explanation: When Rendering Fails
sometimes, iPlotter just doesn't quite render... I couldn't get the Bubble Chart or Polar Area Chart documented on Chart.js to render or the pie chart in Google Charts.
End of explanation
"""


import json
from IPython.display import display, Javascript

def chartjs(chartType, data, options={}, width="500px", height="400px"):
    """ Custom iphython extension allowing chartjs visualizations
    
    Usage:
        chartjs(chartType, data, options, width=1000, height=400)
    
    Args:
        chartType: one of the supported chart type options (line, bar, radar, polarArea, pie, doughnut)
        data: a python dictionary with datasets to be rapresented and related visualization settings, as expected 
              by chart js (see data parameter in http://www.chartjs.org/docs/)
        options: defaults {}; a python dictionary with additional graph options, as expected 
              by chart js (see options parameter in http://www.chartjs.org/docs/)
        width: default 700px
        height: default 400px
        
        NB. data and options structure depends on the chartType
    """
    display(
        Javascript("""
            require(['https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js'], function(chartjs){
                var chartType="%s";
                var data=%s;
                var options=%s;
                var width="%s";
                var height="%s";
                
                element.append('<canvas width="' + width + '" height="' + height + '">s</canvas>');
                var ctx = element.children()[0].getContext("2d");
                
                switch(chartType.toLowerCase()) {
                    
                    case "line":
                        var myChart = new Chart(ctx).Line(data, options);
                        break;
                    case "bar":
                        var myChart = new Chart(ctx).Bar(data, options);
                        break;
                    case "radar":
                        var myChart = new Chart(ctx).Radar(data, options);
                        break;
                    case "polarArea":
                        var myChart = new Chart(ctx).PolarArea(data, options);
                        break;
                    case "pie":
                        var myChart = new Chart(ctx).Pie(data, options);
                        break;
                    case "doughnut":
                        var myChart = new Chart(ctx).Doughnut(data, options);
                        break;
                }
            });
            """ % (chartType, json.dumps(data), json.dumps(options), width, height)
        )
    )

"""
Explanation: In those cases, call in the JavaScript:
(from this gist)
End of explanation
"""


# to run 
data = {
    "labels": [1,2,3,4,5,6],
    "datasets": [
        {
            "label": "Sample dataset",
            "fillColor": "#ffce56",
            "strokeColor": "rgba(151,187,205,1)",
            "pointColor": "rgba(151,187,205,1)",
            "pointStrokeColor": "#fff",
            "pointHighlightFill": "#fff",
            "pointHighlightStroke": "rgba(151,187,205,1)",
            "data": [1, 10, 3, 2, 7, 8]
        }
]}

chartjs("Line", data, width=600)

"""
Explanation: The above is Javascript in a string with the data converted from Python dictionaries into strings.
End of explanation
"""


%%html
<html>
  <head>
    <!--Load the AJAX API-->
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">

      // Load the Visualization API and the corechart package.
      google.charts.load('current', {'packages':['corechart']});

      // Set a callback to run when the Google Visualization API is loaded.
      google.charts.setOnLoadCallback(drawChart);

      // Callback that creates and populates a data table,
      // instantiates the pie chart, passes in the data and
      // draws it.
      function drawChart() {

        // Create the data table.
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Topping');
        data.addColumn('number', 'Slices');
        data.addRows([
          ['Mushrooms', 3],
          ['Onions', 1],
          ['Olives', 1],
          ['Zucchini', 1],
          ['Pepperoni', 2]
        ]);

        // Set chart options
        var options = {'title':'How Much Pizza I Ate Last Night',
                       'width':600,
                       'height':400};

        // Instantiate and draw our chart, passing in some options.
        var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }
    </script>
  </head>

  <body>
    <!--Div that will hold the pie chart-->
    <div id="chart_div" style="width: 700px; height: 410px;"></div>
  </body>
</html>

"""
Explanation: For Google Charts, simply use Jupyter magic methods to turn the cell into html!
End of explanation
"""


# python list
data = [
          ['Task', 'Hours per Day'],
          ['Work',     11],
          ['Eat',      2],
          ['Commute',  2],
          ['Watch TV', 2],
          ['Sleep',    7]
]

# note the double escape to ensure apostrophe is rendered correctly
title = "Mark\\'s Daily Activities"

html_code = """
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load("current", {packages:["corechart"]});
      google.charts.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = google.visualization.arrayToDataTable(%s);

        var options = {
          title: '%s',
          pieHole: 0.4,
        };

        var chart = new google.visualization.PieChart(document.getElementById('donutchart'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>
    <div id="donutchart" style="width: 900px; height: 520px;"></div>
  </body>
</html>
"""% (data, title)

"""
Explanation: To pass Python Functions, copy the HTML into a python string to embed the python data:
End of explanation
"""


# render use jupyter's html function
HTML(html_code)

"""
Explanation: You can also use the newer string.format() in Python to create the html_code string.
End of explanation
"""


