import contextlib
import glob
import os
import re
from functools import partial
from pathlib import Path

import docx
import pandas as pd
from invoke import task
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT as ALIGN
import numpy as np
from babel.numbers import format_currency, format_decimal
from toolz import compose

# plotting
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import seaborn as sns


@contextlib.contextmanager
def directory(dirname=None):
    """
    changes current directory to dirname
    used as with directory(dirname) as dir to
    move out of the changed directory at the end
    :param dirname: directory to change into
    """
    curdir = os.getcwd()
    try:
        if dirname is not None:
            os.chdir(dirname)
        yield Path(dirname or curdir)
    finally:
        os.chdir(curdir)


@task
def install_tools_osx(ctx):
    """
    installs third party tools required to generate diagrams and documents
    from sources including imagemagick, graphviz, pantuml, and pandoc
    :param ctx:
    """
    ctx.run('brew install imagemagick '
            '--with-librsvg --with-pango --with-libwmf --with-openjpeg '
            '--with-ghostscript --with-fftw --with-fontconfig')
    ctx.run('brew install graphviz --with-librsvg --with-freetype '
            '--with-bindings --with-pango')
    ctx.run('brew install plantuml')
    ctx.run('brew install pandoc')


@task
def puml(ctx):
    ctx.run('plantuml -tsvg ./docs/diagrams.puml')


@task
def raster(ctx):
    for svg_path in glob.iglob('./docs/*.svg'):
        cmd = build_raster_command(svg_path)
        print('will run now')
        print(cmd)
        ctx.run(cmd)


def build_raster_command(input_file):
    output_file = re.sub(r'\.svg$', '.png', input_file, 1)
    converter = 'rsvg-convert'
    dpi = 300  # lossless density
    width_in = 6.3  # MS Word A4 page size sans fields
    width_px = int(dpi * width_in)
    size_opts = '--dpi-x={} --width={}'.format(dpi, width_px)
    other_opts = '--format=png --keep-aspect-ratio --background-color=none'
    output_opt = '--output {}'.format(output_file)
    cmd = ' '.join((converter, size_opts, other_opts, output_opt, input_file))
    return cmd


@task(puml, raster)
def dg(ctx):
    pass


@task
def pl(ctx):
    plt.plot([0, 1, 2, 3, 4], [0, 3, 5, 9, 11])
    plt.xlabel('Months')
    plt.ylabel('Books Read')
    plt.savefig('./docs/books_read.png', bbox_inches='tight', dpi=300)


@task
def doc(ctx):
    input_file = 'adding-ds-to-rpa.md'
    output_file = 'adding-ds-to-rpa.docx'
    reference_file = 'style-reference.docx'
    with directory('./docs'):
        ctx.run('pandoc {} -o {} --toc --reference-docx={}'.format(
            input_file, output_file, reference_file))


@task
def doctable(ctx):
    df = pd.read_csv('./docs/flight-options.csv')

    # open an existing document
    doc = docx.Document('./docs/style-reference.docx')

    as_int = partial(format_decimal, format='#')
    as_usd = partial(format_currency, currency='USD')

    s = doc.sections[0]
    width = s.page_width - s.left_margin - s.right_margin

    doc.add_picture('./docs/diagrams_002.png', width=width)

    formatters = {
        'ticket_price': as_usd,
        'total_hours': as_int,
        'trip': as_int,
        'airline': partial(shorten_long_name, width=20),
        'selected': compose({0: 'No', 1: 'Yes'}.get, int)
    }
    add_table(df, doc, table_style='Plain Table 3', formatters=formatters)

    # save the doc
    doc.save('./docs/test.docx')