# coding: utf-8
"""xlsx-keywords:
  - 08_img_shapes
  - 08_img_area
  - 08_img_types
  - 08_img_proportions
  - 09_rsya_banners_wo_img
  - 09_rsya_banners_small_img
"""
from ..review import Recommendation, append_recommendation
from ..xlsx_chart.chart import Chart, chart_add_series, FONT_NAME
from ..const import EXCEL_MAX_ROWS
from .utils import (
    add_cpc_rsya,
    add_ctr_rsya
)
from ..utils import filter_by_adtype, get_cid_bid, get_group_url
import pandas as pd
from fractions import Fraction


def table_img_shapes(df, normalize):
    """08_img_shapes"""
    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[(df.ShowsRSYA > 0), :].copy()

    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .groupby(["YTImageSizeHeight", "YTImageSizeWidth"], as_index=False)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "DirectBannerID": lambda x: x.unique().size,
                    "ImageHash": lambda x: x.unique().size
                })
                .rename(columns={
                    "ImageHash": "UniqImgCnt",
                    "DirectBannerID": "BannersCnt"
                })
                .assign(area=lambda x: x.YTImageSizeHeight * x.YTImageSizeWidth)
                .sort_values("area")
                .reset_index(drop=True)
                .drop("area", axis=1))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "YTImageSizeHeight": u"Высота",
        "YTImageSizeWidth": u"Ширина",
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "UniqImgCnt": u"Кол-во разных картинок",
        "BannersCnt": u"Кол-во объявлений"
    }, inplace=True)

    if normalize:
        sum_col = [
            u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
            u"Кол-во разных картинок", u"Кол-во объявлений"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

    df_chart = df_chart.loc[:, [u"Высота", u"Ширина",
                                u"Кол-во объявлений", u"Кол-во разных картинок",
                                u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
                                u"CPC (сети)", u"CTR (сети)"]]

    setattr(df_chart, "formats", {u"Кол-во объявлений": "int",
                                  u"Кол-во разных картинок": "int",
                                  u"Показы (сети)": "int",
                                  u"Клики (сети)": "int",
                                  u"Расходы (сети)": "float",
                                  u"CPC (сети)": "float",
                                  u"CTR (сети)": "percent"})

    return df_chart


def table_img_area(df, normalize):
    """08_img_area"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[(df.ShowsRSYA > 0), :].copy()

    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .assign(YTImageSizeArea=lambda x: (x.YTImageSizeHeight * x.YTImageSizeWidth).pow(.5).round(-1))
                .groupby(["YTImageSizeArea", ], as_index=False)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "DirectBannerID": lambda x: x.unique().size,
                    "ImageHash": lambda x: x.unique().size
                })
                .rename(columns={
                    "ImageHash": "UniqImgCnt",
                    "DirectBannerID": "BannersCnt"
                })
                .sort_values("YTImageSizeArea")
                .reset_index(drop=True))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "YTImageSizeArea": u"Квадратура изображения",
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "UniqImgCnt": u"Кол-во разных картинок",
        "BannersCnt": u"Кол-во объявлений"
    }, inplace=True)

    if normalize:
        sum_col = [
            u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
            u"Кол-во разных картинок", u"Кол-во объявлений"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

    df_chart = df_chart.loc[:, [u"Квадратура изображения",
                                u"Кол-во объявлений",
                                u"Кол-во разных картинок",
                                u"Показы (сети)",
                                u"Клики (сети)",
                                u"Расходы (сети)",
                                u"CPC (сети)",
                                u"CTR (сети)"]]

    if normalize:
        formats = {
            u"Квадратура изображения": "string",
            u"Кол-во объявлений": "percent",
            u"Кол-во разных картинок": "percent",
            u"Показы (сети)": "percent",
            u"Клики (сети)": "percent",
            u"Расходы (сети)": "percent",
            u"CPC (сети)": "float",
            u"CTR (сети)": "float"}
    else:
        formats = {
            u"Квадратура изображения": "string",
            u"Кол-во объявлений": "int",
            u"Кол-во разных картинок": "int",
            u"Показы (сети)": "int",
            u"Клики (сети)": "int",
            u"Расходы (сети)": "float",
            u"CPC (сети)": "float",
            u"CTR (сети)": "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def plot_img_area(writer, sheet_name, df):
    """
    (ExcelWriter, str, DataFrame) -> ExcelWriter
    08_img_area
    """

    sheet = writer.book.get_worksheet_by_name(sheet_name)
    max_idx = df.shape[0] + 1

    # Create chart
    chart = Chart(writer.book, "scatter", "straight_with_markers", u'Используемая квадратура изображений')

    # Add data series.
    chart_add_series(chart, 0, {
        'values': u"='%s'!N2:N%d" % (sheet_name, max_idx),
        "categories": u"='%s'!K2:K%d" % (sheet_name, max_idx),
        "name": u"='%s'!N1" % sheet_name,
        "line": {'none': True},
        "marker": {"size": 15},
        "data_labels": {'value': None}})
    chart_add_series(chart, 1, {
        'values': u"='%s'!O2:O%d" % (sheet_name, max_idx),
        "categories": u"='%s'!K2:K%d" % (sheet_name, max_idx),
        "name": u"='%s'!O1" % sheet_name,
        "line": {'none': True},
        "marker": {"size": 15},
        "data_labels": {'value': None}})
    chart_add_series(chart, 2, {
        'values': u"='%s'!P2:P%d" % (sheet_name, max_idx),
        "categories": u"='%s'!K2:K%d" % (sheet_name, max_idx),
        "name": u"='%s'!P1" % sheet_name,
        "line": {'none': True},
        "marker": {"size": 15},
        "data_labels": {'value': None}})

    chart.set_y_axis({
        "visible": True,
        "name": u"Доля от общего",
        'name_font': {
            "size": 14,
            "bold": False,
            "name": FONT_NAME
        },
        'num_font': {
            "size": 14,
            "bold": False,
            "name": FONT_NAME
        },
        'num_format': '#0%',
        'major_tick_mark': 'none',
        'minor_tick_mark': 'none',
        "min": 0,
    })

    chart.set_x_axis({
        "visible": True,
        "name": u"Квадратура",
        'major_gridlines': {
            'visible': True,
            'line': {'width': 0.75,
                     'dash_type': 'dash',
                     'color': '#868686'}},  # grey
        'name_font': {
            "size": 14,
            "bold": False,
            "name": FONT_NAME
        },
        'num_font': {
            "size": 14,
            "bold": False,
            "name": FONT_NAME
        },
        'num_format': '### ##0',
        'major_tick_mark': 'none',
        'major_unit': 250,
        'minor_tick_mark': 'none',
        "min": 0,
    })

    sheet.insert_chart("A%d" % (max_idx + 2), chart)

    return writer


def classify_shape(width, height):

    if width == 0 and height == 0:
        return None
    if width <= 0 or height <= 0:
        raise ValueError("invalid shape: %s, %s" % (width, height))

    if width == height:
        return "square"
    if width > height:
        return "horizontal"
    if width < height:
        return "vertically"


def table_img_types_detailed(df, normalize):
    """08_img_types"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[(df.ShowsRSYA > 0) & df.HasYTImageSize, :].copy()
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart["YTImageSizeType"] = df_chart.apply(
        lambda row: classify_shape(width=row["YTImageSizeWidth"], height=row["YTImageSizeHeight"]),
        axis=1)

    df_chart = df_chart.loc[~(df_chart["YTImageSizeType"].isnull()), :]
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .groupby(["YTImageSizeIsWide", "YTImageSizeType"], as_index=True)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "DirectBannerID": lambda x: x.unique().size,
                    "ImageHash": lambda x: x.unique().size
                })
                .rename(columns={
                    "ImageHash": "UniqImgCnt",
                    "DirectBannerID": "BannersCnt"
                }))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "UniqImgCnt": u"Кол-во разных картинок",
        "BannersCnt": u"Кол-во объявлений"
    }, inplace=True)
    df_chart.rename(index={
        "square": u"квадратный",
        "horizontal": u"горизонтальный",
        "vertically": u"вертикальный",
        True: u"Да",
        False: u"Нет"
    }, inplace=True)
    df_chart.index.names = [u"Широкоформатный баннер", u"Тип изображения"]

    if normalize:
        sum_col = [
            u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
            u"Кол-во разных картинок", u"Кол-во объявлений"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

        df_chart = df_chart.loc[[(u"Нет", u"квадратный"),
                                 (u"Нет", u"горизонтальный"),
                                 (u"Нет", u"вертикальный"),
                                 (u"Да", u"квадратный"),
                                 (u"Да", u"горизонтальный"),
                                 (u"Да", u"вертикальный")],
                                [u"Кол-во объявлений",
                                 u"Кол-во разных картинок",
                                 u"Показы (сети)",
                                 u"Клики (сети)",
                                 u"Расходы (сети)",
                                 u"CPC (сети)",
                                 u"CTR (сети)"]].fillna(0)

    if normalize:
        formats = {u"Кол-во объявлений": "percent",
                   u"Кол-во разных картинок": "percent",
                   u"Показы (сети)": "percent",
                   u"Клики (сети)": "percent",
                   u"Расходы (сети)": "percent",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "float"}
    else:
        formats = {u"Кол-во объявлений": "int",
                   u"Кол-во разных картинок": "int",
                   u"Показы (сети)": "int",
                   u"Клики (сети)": "int",
                   u"Расходы (сети)": "float",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_img_types(df, normalize):
    """08_img_types"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[(df.ShowsRSYA > 0) & df.HasYTImageSize, :].copy()
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart["YTImageSizeType"] = df_chart.apply(lambda row: classify_shape(width=row["YTImageSizeWidth"],
                                                                            height=row["YTImageSizeHeight"]), axis=1)

    df_chart = df_chart.loc[~(df_chart["YTImageSizeType"].isnull()), :]
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .groupby(["YTImageSizeType"], as_index=True)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "DirectBannerID": lambda x: x.unique().size,
                    "ImageHash": lambda x: x.unique().size
                })
                .rename(columns={
                    "ImageHash": "UniqImgCnt",
                    "DirectBannerID": "BannersCnt"
                }))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "UniqImgCnt": u"Кол-во разных картинок",
        "BannersCnt": u"Кол-во объявлений"
    }, inplace=True)
    df_chart.rename(index={
        "square": u"квадратный",
        "horizontal": u"горизонтальный",
        "vertically": u"вертикальный",
    }, inplace=True)
    df_chart.index.names = [u"Тип изображения"]

    if normalize:
        sum_col = [
            u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
            u"Кол-во разных картинок", u"Кол-во объявлений"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

    df_chart = df_chart.loc[[u"квадратный",
                             u"горизонтальный",
                             u"вертикальный"],
                            [u"Кол-во объявлений",
                             u"Кол-во разных картинок",
                             u"Показы (сети)",
                             u"Клики (сети)",
                             u"Расходы (сети)",
                             u"CPC (сети)",
                             u"CTR (сети)"]].fillna(0)

    if normalize:
        formats = {u"Кол-во объявлений": "percent",
                   u"Кол-во разных картинок": "percent",
                   u"Показы (сети)": "percent",
                   u"Клики (сети)": "percent",
                   u"Расходы (сети)": "percent",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "float"}
    else:
        formats = {u"Кол-во объявлений": "int",
                   u"Кол-во разных картинок": "int",
                   u"Показы (сети)": "int",
                   u"Клики (сети)": "int",
                   u"Расходы (сети)": "float",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_img_types_width(df, normalize):
    """08_img_types"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[(df.ShowsRSYA > 0) & df.HasYTImageSize, :].copy()
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart["YTImageSizeType"] = df_chart.apply(
        lambda row: classify_shape(width=row["YTImageSizeWidth"], height=row["YTImageSizeHeight"]),
        axis=1)

    df_chart = df_chart.loc[~(df_chart["YTImageSizeType"].isnull()), :]
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .groupby(["YTImageSizeIsWide"], as_index=True)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "DirectBannerID": lambda x: x.unique().size,
                    "ImageHash": lambda x: x.unique().size
                })
                .rename(columns={
                    "ImageHash": "UniqImgCnt",
                    "DirectBannerID": "BannersCnt"
                }))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "UniqImgCnt": u"Кол-во разных картинок",
        "BannersCnt": u"Кол-во объявлений"
    }, inplace=True)
    df_chart.rename(index={
        True: u"широкоформатный",
        False: u"не широкоформатный"
    }, inplace=True)
    df_chart.index.names = [u"Широкоформатность"]

    if normalize:
        sum_col = [
            u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
            u"Кол-во разных картинок", u"Кол-во объявлений"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

    df_chart = df_chart.loc[[u"широкоформатный",
                             u"не широкоформатный"],
                            [u"Кол-во объявлений",
                             u"Кол-во разных картинок",
                             u"Показы (сети)",
                             u"Клики (сети)",
                             u"Расходы (сети)",
                             u"CPC (сети)",
                             u"CTR (сети)"]].fillna(0)

    if normalize:
        formats = {u"Кол-во объявлений": "percent",
                   u"Кол-во разных картинок": "percent",
                   u"Показы (сети)": "percent",
                   u"Клики (сети)": "percent",
                   u"Расходы (сети)": "percent",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "float"}
    else:
        formats = {u"Кол-во объявлений": "int",
                   u"Кол-во разных картинок": "int",
                   u"Показы (сети)": "int",
                   u"Клики (сети)": "int",
                   u"Расходы (сети)": "float",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_group_img_formats(df, normalize):
    """08_img_types"""

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart.loc[(df_chart.ShowsRSYA > 0)]

    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = df_chart.loc[:, ['GroupID', 'GroupYTImageFormat', 'ShowsRSYA', 'ClicksRSYA', 'CostRSYA']]

    df_chart = (df_chart
                .groupby(["GroupYTImageFormat"], as_index=True)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "GroupID": lambda x: x.unique().size
                })
                .rename(columns={"GroupID": "GroupsCnt"})
                )

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "GroupsCnt": u"Кол-во групп"
    }, inplace=True)
    df_chart.rename(index={
        "standart": u"Без широкоформатных",
        "wide": u"Без стандартных",
        "both": u"Оба формата",
        "small": u"Маленькие изображения",
        "None": u"Без изображений",
    }, inplace=True)
    df_chart.index.names = [u"Тип формата"]

    if normalize:
        sum_col = [u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)", u"Кол-во групп"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

        # Лимиты из головы эксперта, можно менять
        try:
            group_img_none_b, group_img_none_s = df_chart.loc[u"Без изображений", [u"Кол-во групп", u"Показы (сети)"]]
        except KeyError:
            group_img_none_b, group_img_none_s = 0., 0.
        if group_img_none_b > 0. or group_img_none_s > 0:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="08_img_types",
                title=u"Изображения",
                snippet=u"Группы объявлений без изображений: %.0f%% объявлений (%.0f%% показов в сетях)" %
                        (group_img_none_b * 100., group_img_none_s * 100.),
                cell="M26",
                importance_lvl=2)
            append_recommendation(df, Rec, uniq=False)

        # Лимиты из головы эксперта, можно менять
        try:
            group_img_w_b, group_img_w_s = df_chart.loc[[u"Без стандартных", u"Оба формата"], [u"Кол-во групп", u"Показы (сети)"]].sum()
        except KeyError:
            group_img_w_b, group_img_w_s = 1., 1.
        if group_img_w_b < 0.8 or group_img_w_s < 0.8:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="08_img_types",
                title=u"Изображения",
                snippet=u"Широкоформатные изображения присутствуют у %.0f%% объявлений (%.0f%% показов в сетях)" %
                        (group_img_w_b * 100., group_img_w_s * 100.),
                cell="M22",
                importance_lvl=2)
            append_recommendation(df, Rec, uniq=False)

    df_chart = df_chart.loc[
        [u"Без широкоформатных",
         u"Без стандартных",
         u"Оба формата",
         u"Маленькие изображения",
         u"Без изображений"],
        [u"Кол-во групп",
         u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
         u"CPC (сети)", u"CTR (сети)"]].fillna(0)

    if normalize:
        formats = {u"Кол-во групп": "percent",
                   u"Показы (сети)": "percent",
                   u"Клики (сети)": "percent",
                   u"Расходы (сети)": "percent",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "float"}
    else:
        formats = {u"Кол-во групп": "int",
                   u"Показы (сети)": "int",
                   u"Клики (сети)": "int",
                   u"Расходы (сети)": "float",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_rsya_groups_by_img_formats(df, table_type='full'):
    """08_rsya_groups_by_formats"""

    assert table_type in ['full', 'without_images'], 'unknown table_type: %s' % table_type

    df = filter_by_adtype(df, "TEXT_AD")
    if table_type == 'full':
        df = (df.loc[
              (df.ShowsRSYA > 0) &
              (df.GroupYTImageFormat != 'both'), :]
              .copy())
    elif table_type == 'without_images':
        df = df.loc[df.ShowsRSYA > 0, :].copy()
        df = df.drop(df[df['GroupYTImageFormat'].isin(['both', 'None'])].index)

    if df is None or df.shape[0] == 0:
        return None

    df["GroupURL"] = df.apply(lambda row: get_group_url(row['CampaignID'], row['GroupID']), axis=1)

    df = (df[['GroupID', 'GroupURL', 'GroupYTImageFormat', 'ShowsRSYA', 'ClicksRSYA', 'CostRSYA']]
          .groupby(["GroupID", "GroupURL", "GroupYTImageFormat"], as_index=False)
          .agg({"ShowsRSYA": pd.np.sum,
                "ClicksRSYA": pd.np.sum,
                "CostRSYA": pd.np.sum})
          .sort_values("ShowsRSYA", ascending=False)
          .head(EXCEL_MAX_ROWS)
          )

    add_cpc_rsya(df)
    add_ctr_rsya(df)

    df["GroupYTImageFormat"] = df.GroupYTImageFormat.replace(to_replace={
        "standart": u"Без широкоформатных изображений",
        "wide": u"Без стандартных изображений",
        "both": u"Оба формата",
        "small": u"Маленькие изображения",
        "None": u"Без изображений"})

    df.rename(
        columns={
            "GroupID": u"Группа №",
            "GroupURL": u"Ссылка на группу",
            "GroupYTImageFormat": u"Форматы изображений в группе",
            "ShowsRSYA": u"Показы (сети)",
            "ClicksRSYA": u"Клики (сети)",
            "CostRSYA": u"Расходы (сети)",
            "CPCRSYA": u"CPC (сети)",
            "CTRRSYA": u"CTR (сети)"},
        inplace=True)

    df = df.loc[:, [u"Группа №", u"Ссылка на группу", u"Форматы изображений в группе",
                    u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)", u"CPC (сети)", u"CTR (сети)"]]

    setattr(df, "formats", {u"Группа №": "string",
                            u"Форматы изображений в группе": "string",
                            u"Показы (сети)": "int",
                            u"Клики (сети)": "int",
                            u"Расходы (сети)": "float",
                            u"CPC (сети)": "float",
                            u"CTR (сети)": "percent"})

    return df


def plot_img_type(writer, sheet_name, cell, df):
    """
    (ExcelWriter, str, DataFrame) -> ExcelWriter
    01_highlight_type
    """

    sheet = writer.book.get_worksheet_by_name(sheet_name)

    # Create chart
    chart = Chart(writer.book, "bar", "percent_stacked", u'Типоразмеры картинок')

    # Add data series.
    chart_add_series(chart, 0, {
        'values': u"='%s'!B2:F2" % sheet_name,
        "categories": u"='%s'!B1:F1" % sheet_name,
        "name": u"='%s'!A2" % sheet_name})
    chart_add_series(chart, 1, {
        'values': u"='%s'!B3:F3" % sheet_name,
        "categories": u"='%s'!B1:F1" % sheet_name,
        "name": u"='%s'!A3" % sheet_name})
    chart_add_series(chart, 2, {
        'values': u"='%s'!B4:F4" % sheet_name,
        "categories": u"='%s'!B1:F1" % sheet_name,
        "name": u"='%s'!A4" % sheet_name})

    # Insert the chart into the worksheet.
    sheet.insert_chart(cell, chart)

    return writer


def plot_img_type_p(writer, sheet_name, cell, df):
    """
    (ExcelWriter, str, DataFrame) -> ExcelWriter
    01_highlight_type
    """

    sheet = writer.book.get_worksheet_by_name(sheet_name)

    # Create chart
    chart = Chart(writer.book, "bar", "percent_stacked", u'Типоразмеры картинок')

    # Add data series.
    label_fmt = {'value': True, 'num_format': '0%'}
    chart_add_series(chart, 0, {
        'values': u"='%s'!M2:Q2" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!M1:Q1" % sheet_name,
        "name": u"='%s'!L2" % sheet_name})
    chart_add_series(chart, 1, {
        'values': u"='%s'!M3:Q3" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!M1:Q1" % sheet_name,
        "name": u"='%s'!L3" % sheet_name})
    chart_add_series(chart, 2, {
        'values': u"='%s'!M4:Q4" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!M1:Q1" % sheet_name,
        "name": u"='%s'!L4" % sheet_name})

    # Insert the chart into the worksheet.
    sheet.insert_chart(cell, chart)

    return writer


def classify_shape_proportion(width, height):

    if width == 0 and height == 0:
        return None
    if width <= 0 or height <= 0:
        raise ValueError("invalid shape: %s, %s" % (width, height))

    # Округление до сотен
    ratio = Fraction(int(round(width, -2)), int(round(height, -2)))

    return "%sx%s" % (ratio.numerator, ratio.denominator)


def table_img_proportions(df, normalize):
    """08_img_proportions"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[(df.ShowsRSYA > 0) & df.HasYTImageSize, :].copy()
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart["YTImageSizeProportion"] = df_chart.apply(
        lambda row: classify_shape_proportion(width=row["YTImageSizeWidth"], height=row["YTImageSizeHeight"]),
        axis=1)

    df_chart = df_chart.loc[~(df_chart["YTImageSizeProportion"].isnull()), :]
    if df_chart is None or df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .groupby(["YTImageSizeProportion"], as_index=True)
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum,
                    "DirectBannerID": lambda x: x.unique().size,
                    "ImageHash": lambda x: x.unique().size
                })
                .rename(columns={
                    "ImageHash": "UniqImgCnt",
                    "DirectBannerID": "BannersCnt"
                })
                .sort_values("ShowsRSYA", ascending=False))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "UniqImgCnt": u"Кол-во разных картинок",
        "BannersCnt": u"Кол-во объявлений"
    }, inplace=True)
    df_chart.index.names = [u"Пропорция, ШxВ"]

    if normalize:
        sum_col = [
            u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
            u"Кол-во разных картинок", u"Кол-во объявлений"]
        max_col = [u"CPC (сети)", u"CTR (сети)"]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

    df_chart = df_chart.loc[:, [u"Кол-во объявлений", u"Кол-во разных картинок",
                                u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)",
                                u"CPC (сети)", u"CTR (сети)"]].fillna(0)

    if normalize:
        formats = {u"Кол-во объявлений": "percent",
                   u"Кол-во разных картинок": "percent",
                   u"Показы (сети)": "percent",
                   u"Клики (сети)": "percent",
                   u"Расходы (сети)": "percent",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "float"}
    else:
        formats = {u"Кол-во объявлений": "int",
                   u"Кол-во разных картинок": "int",
                   u"Показы (сети)": "int",
                   u"Клики (сети)": "int",
                   u"Расходы (сети)": "float",
                   u"CPC (сети)": "float",
                   u"CTR (сети)": "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_rsya_banners_wo_img(df):
    """09_rsya_banners_wo_img"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df
                .loc[(~df.HasYTImageSize) &
                     (df.ShowsRSYA > 0),
                     ["CampaignID", "CampaignName", "DirectBannerID",
                      "Title", "Body",
                      "ShowsRSYA", "ClicksRSYA", "CostRSYA"]]
                .groupby(["CampaignID", "CampaignName", "DirectBannerID", "Title", "Body"])
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum})
                .sort_values("ShowsRSYA", ascending=False)
                .head(EXCEL_MAX_ROWS))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(
        columns={
            "ShowsRSYA": u"Показы (сети)",
            "ClicksRSYA": u"Клики (сети)",
            "CostRSYA": u"Расходы (сети)",
            "CPCRSYA": u"CPC (сети)",
            "CTRRSYA": u"CTR (сети)"},
        inplace=True)

    if df_chart.shape[0] == 0:
        return None

    df_chart.index.names = [u"Кампания №", u"Название кампании", u"Баннер №", u"Заголовок", u"Объявление"]
    df_chart = df_chart.loc[:, [u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)", u"CPC (сети)", u"CTR (сети)"]]

    setattr(df_chart, "formats", {u"Показы (сети)": "int",
                                  u"Клики (сети)": "int",
                                  u"Расходы (сети)": "float",
                                  u"CPC (сети)": "float",
                                  u"CTR (сети)": "percent"})

    return df_chart


def table_rsya_banners_small_img(df):
    """09_rsya_banners_small_img"""

    df = filter_by_adtype(df, "TEXT_AD")
    df_chart = df.loc[df.HasYTImageSize &
                      (df.YTImageSizeWidth < 450.) &
                      (df.ShowsRSYA > 0),
                      ["CampaignID", "CampaignName", "DirectBannerID",
                       "Title", "Body", "YTImageSizeWidth", "YTImageSizeHeight",
                       "ShowsRSYA", "ClicksRSYA", "CostRSYA"]]

    if df_chart.shape[0] == 0:
        return None

    df_chart = (df_chart
                .assign(HelperUrlBid=lambda df:
                        df.apply(lambda row: get_cid_bid(row["CampaignID"], row["DirectBannerID"]),
                                 axis=1))
                .groupby(["CampaignID", "CampaignName", "DirectBannerID", "HelperUrlBid",
                          "Title", "Body", "YTImageSizeWidth", "YTImageSizeHeight"])
                .agg({
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum})
                .sort_values("ShowsRSYA", ascending=False)
                .head(EXCEL_MAX_ROWS))

    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(
        columns={
            "ShowsRSYA": u"Показы (сети)",
            "ClicksRSYA": u"Клики (сети)",
            "CostRSYA": u"Расходы (сети)",
            "CPCRSYA": u"CPC (сети)",
            "CTRRSYA": u"CTR (сети)"
        }, inplace=True)

    df_chart.index.names = [
        u"Кампания №", u"Название кампании", u"Баннер №", u"Ссылка на баннер",
        u"Заголовок", u"Объявление", u"Ширина", u"Высота"
    ]
    df_chart = df_chart.loc[:, [u"Показы (сети)", u"Клики (сети)", u"Расходы (сети)", u"CPC (сети)", u"CTR (сети)"]]

    setattr(df_chart, "formats", {u"Показы (сети)": "int",
                                  u"Клики (сети)": "int",
                                  u"Расходы (сети)": "float",
                                  u"CPC (сети)": "float",
                                  u"CTR (сети)": "percent"})

    return df_chart
