"""Run ezCharts demo."""
import argparse

from dominate.tags import p
import numpy as np
import pandas as pd
from pkg_resources import resource_filename

import ezcharts as ezc
from ezcharts import util
from ezcharts.components.ezchart import EZChart
from ezcharts.components.fastcat import SeqSummary
from ezcharts.components.nextclade import NextClade, NXTComponent
from ezcharts.components.reports.labs import LabsReport
from ezcharts.components.theme import LAB_head_resources
from ezcharts.layout.snippets import DataTable
from ezcharts.layout.snippets import Grid
from ezcharts.layout.snippets import OffCanvas
from ezcharts.layout.snippets import Progress
from ezcharts.layout.snippets import Stats
from ezcharts.layout.snippets import Tabs
from ezcharts.layout.snippets.cards import Cards
from ezcharts.layout.snippets.cards import ICard
from ezcharts.plots import Plot
from ezcharts.plots.ideogram import ideogram

# Setup simple globals
WORKFLOW_NAME = 'wf-template'
REPORT_TITLE = f'{WORKFLOW_NAME}-report'


def main(args):
    """Demo for ezCharts functionality."""
    logger = util.get_named_logger("ezChrtDemo")

    # Good location to prepare plots
    logger.info('Building plots')

    # Example data
    raw_df = pd.DataFrame({
        # as laid out in echarts docs for a dataset
        'product': [
            'Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'],
        '2015': [43.3, 83.1, 86.4, 72.4],
        '2016': [85.8, 73.4, 65.2, 53.9],
        '2017': [93.7, 55.1, 82.5, 39.1]
    })
    # how we'd likely normally have it
    example_df = raw_df.melt(
        id_vars=['product'], value_vars=['2015', '2016', '2017'],
        var_name='year', value_name='sales')

    def example_plot(style="line") -> Plot:
        """Create example plot."""
        if style == "line":
            plot = ezc.lineplot(data=example_df, x='year', y='sales', hue='product')
        elif style == "scatter":
            plot = ezc.scatterplot(data=example_df, x='year', y='sales', hue='product')
        elif style == 'histogram':
            hist_data = pd.DataFrame(
                        [np.random.normal(loc=10.0, size=1000),
                         np.random.normal(loc=12.0, size=1000),
                         np.random.normal(loc=14.0, size=1000)]).T
            hist_data.columns = ['sample1', 'sample2', 'sample3']
            plot = ezc.histplot(hist_data, bins=50, stat='proportion')

            plot.xAxis.name = 'Read length'
            plot.yAxis.name = 'Number of reads'
        elif style == "bar":
            plot = ezc.barplot(data=example_df, x='year', y='sales', hue='product')
        elif style == "heatmap":
            # make data a matrix like you would expect for a heatmap
            df = raw_df.set_index([raw_df.columns[0]])
            # set the names of the axes
            df = df.rename_axis("Product")
            df = df.rename_axis("Year", axis=1)
            plot = ezc.heatmap(data=df)
        else:
            raise ValueError("Unknown plot style")
        plot.title = {"text": f"Example {style} chart"}
        return plot

    # Then, time to construct a report
    logger.info('Building report')

    # Example data
    params = resource_filename('ezcharts', "data/test/params.json")
    versions = resource_filename('ezcharts', "data/test/versions.txt")
    nxt_json = resource_filename('ezcharts', "data/test/nextclade.json")
    fastcat_results = resource_filename(
        'ezcharts', "data/test/fastcat.stats.gz")

    # Create report
    # Note we need to add nextclade as a resource
    report = LabsReport(
        REPORT_TITLE, WORKFLOW_NAME, params, versions,
        head_resources=[*LAB_head_resources, NXTComponent])

    # Add a header badge via a method on the report element.
    report.add_badge('Test badge', bg_class="bg-primary")

    # Make a progress bar for the median accuracy box
    median_accuracy = Progress(
            value_min=0,
            value_max=100,
            value_now=98.9,
            bar_cls="progress-bar-striped",
            height=50)

    # Add something directly to main_content.
    with report.main_content:
        # Stats is a snippet, but we could also just add any html
        # tags here. Snippets are little reusable portions of html,
        # styles and or scripts in python class format. They often
        # expose methods for adding content to them in a simple way.
        # E.g.
        Stats(
            columns=3,
            items=[
                ('1213986', 'Read count'),
                (median_accuracy, 'Median accuracy'),
                ('10213 bp', 'Some other stat')
            ])

    # Add sequence summary component
    with report.add_section('Sequence summaries', 'Summaries'):
        SeqSummary(fastcat_results)

    # This also adds to main_content, but provides a nice
    # container snippet as a starting context.
    with report.add_section('Controls', 'Controls'):
        # This is an example of how to use bootstrap cards
        Cards(
            columns=2,
            items=[
                ICard(
                    head="Positive",
                    body="The positive passed",
                    footer="All postive controls within threshold",
                    classes="bg-success text-white"),
                ICard(
                    head="No Template Control",
                    body="The NTC failed",
                    footer="NTC outside set thresholds.",
                    classes="bg-danger text-white")])
        OffCanvas(
            label="More details (Offcanvas demo)",
            title="Details of Controls",
            body="You can put more details here....")

    # This also adds to main_content, but provides a nice
    # container snippet as a starting context.
    with report.add_section('Alignment results', 'Results'):
        # This is the tabbed section with ezcharts!
        tabs = Tabs()
        with tabs.add_tab('Summary'):
            # Grids are snippets that provide responsive
            # layouts via css grid
            with Grid():
                EZChart(example_plot("line"), 'epi2melabs')
                EZChart(example_plot("scatter"), 'epi2melabs')
                EZChart(example_plot("bar"), 'epi2melabs')
                EZChart(example_plot("histogram"), 'epi2melabs')
        with tabs.add_tab('Accuracy'):
            p("This is a mixed tab!")
            EZChart(example_plot(), 'epi2melabs')
        with tabs.add_tab('Depth'):
            p('Testing, testing, 1 2 3')

        # Dropdowns are nested one more level
        with tabs.add_dropdown_menu('Example', change_header=False):
            with tabs.add_dropdown_tab('First'):
                EZChart(example_plot(), 'epi2melabs')
            with tabs.add_dropdown_tab('Second'):
                p("This is the second dropdown item.")
                # set dodge=False for a stacked barplot
                plot = ezc.barplot(
                    data=example_df, x='year', y='sales', hue='product', dodge=False
                )
                EZChart(plot, 'epi2melabs')

    with report.add_section('Nextclade results', 'Nextclade', True):
        NextClade(nxt_json)

    with report.add_section('Heatmap', 'Heatmap'):
        EZChart(example_plot("heatmap"), 'epi2melabs')

    with report.add_section('Human Genome', 'Genome'):
        EZChart(
            ideogram(blocks='cytobands'),
            'epi2melabs', height="800px")

    with report.add_section('Table', 'Table'):
        tabs = Tabs()
        with tabs.add_tab('Table'):
            df = pd.DataFrame(np.random.random((4, 4))) * 10
            df.columns = pd.MultiIndex.from_product(
                [['sample1', 'sample2'], ['mapped', 'unmapped']])
            df['chr'] = [1, 2, 3, 4]
            df = df.set_index('chr', drop=True)
            DataTable.from_pandas(df, use_index=True)
        with tabs.add_tab('Export'):
            df_simple = pd.DataFrame(np.random.random((4, 2))) * 10
            df_simple.columns = ['sample1', 'sample2']
            DataTable.from_pandas(df_simple, export=True, file_name='samples')

    logger.info('Reticulating splines')
    report.write(args.output)


def argparser():
    """Argument parser for entrypoint."""
    parser = argparse.ArgumentParser(
        "ezcharts demo",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        add_help=False)
    parser.add_argument(
        "--output", default="ezcharts_demo_report.html",
        help="Output HTML file.")
    return parser
