#!/usr/bin/env python
## Copyright (c) 2019, Alliance for Open Media. All rights reserved
##
## This source code is subject to the terms of the BSD 2 Clause License and
## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
## was not distributed with this source code in the LICENSE file, you can
## obtain it at www.aomedia.org/license/software. If the Alliance for Open
## Media Patent License 1.0 was not distributed with this source code in the
## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
##
__author__ = "maggie.sun@intel.com, ryan.lei@intel.com"

import os
import xlsxwriter
import xlrd
import re
from Config import QPs, DnScaleRatio, QualityList, VbaBinFile, CvxH_WtRows,\
    CvxH_WtLastCol, LoggerName, CalcBDRateInExcel, CvxH_WtCols, CvxHDataRows, CvxHDataStartCol
from Utils import GetShortContentName, CalcRowsClassAndContentDict
from CalcBDRate import BD_RATE
import logging

subloggername = "PostAnalysisSummary"
loggername = LoggerName + '.' + '%s' % subloggername
logger = logging.getLogger(loggername)

# give all paths including convex hull result file (only one file for each
# content) to generate summary file for all contents in Input path
# assume all content's result has same test settings

################################################################################
### Helper Functions ###########################################################
def GetRDSummaryFileName(encMethod, codecName, preset, path):
    filetype = 'xlsm' if CalcBDRateInExcel else 'xlsx'
    name = 'ConvexHullRDSummary_ScaleAlgosNum_%d_%s_%s_%s.%s'\
           % (len(DnScaleRatio), encMethod, codecName, preset, filetype)
    return os.path.join(path, name)

def GetConvexHullDataSummaryFileName(encMethod, codecName, preset, path):
    name = 'ConvexHullData_ScaleAlgosNum_%d_%s_%s_%s.xlsx'\
           % (len(DnScaleRatio), encMethod, codecName, preset)
    return os.path.join(path, name)

def SweepScalingAlgosInOneResultFile(resultfiles):
    dnscls = []
    upscls = []

    # here assume all result files includes same combinations of dn and up scaling algos
    # that is, same number of sheet and sheet names
    file = resultfiles[0]
    if os.path.isfile(file):
        rdwb = xlrd.open_workbook(file)
    else:
        return dnscls, upscls
    if rdwb is not None:
        shtnms = rdwb.sheet_names()
        for shtname in shtnms:
            item = re.findall(r"(.+)\-\-(.+)", shtname)
            dnsl = item[0][0]
            upsl = item[0][1]
            dnscls.append(dnsl)
            upscls.append(upsl)

    return dnscls, upscls

def CopyResultDataToSummaryFile_Onesheet(sht, wt_cols, resultfiles):
    rdrows = CvxH_WtRows
    rd_endcol = CvxH_WtLastCol

    shtname = sht.get_name()
    sht.write(1, 0, 'Content Class')
    sht.write(1, 1, 'Content Name')
    sht.write(1, 2, 'QP')
    for residx, col in zip(range(len(DnScaleRatio)), wt_cols):
        sht.write(0, col, 'Scaling Ratio = %.2f' % (DnScaleRatio[residx]))
        sht.write(1, col, 'Bitrate(kbps)')
        qtynames = ['%s' % qty for qty in QualityList]
        sht.write_row(1, col + 1, qtynames)

    # copy the results data from each content's result file to corresponding
    # location in summary excel file
    for (cls, clip_list), row_class in zip(ClipDict.items(), Rows_Class):
        sht.write(row_class, 0, cls)
        rows_content = [i * len(QPs) for i in range(len(clip_list))]
        for clip, row_cont in zip(clip_list, rows_content):
            key = GetShortContentName(clip.file_name)
            sht.write(row_class + row_cont, 1, key)
            rdwb = None
            for resfile in resultfiles:
                if key in resfile:
                    rdwb = xlrd.open_workbook(resfile)
                    rdsht = rdwb.sheet_by_name(shtname)
                    for i, rdrow in zip(range(len(QPs)), rdrows):
                        data = rdsht.row_values(rdrow, 0, rd_endcol + 1)
                        sht.write_row(row_class + row_cont + i, 2, data)
                    break
            assert rdwb is not None
            if rdwb is None:
                logger.warning("not find convex hull result file for content:%s"
                               % clip.file_name)

def CalBDRateWithExcel_OneSheet(sht, cols, cols_bdmtrs, cellformat):
    row_refst = 0
    bdstep = len(QPs) - 1
    for cols_bd, residx in zip(cols_bdmtrs, range(1, len(DnScaleRatio))):
        sht.write(0, cols_bd, 'BD-Rate %.2f vs. %.2f' % (DnScaleRatio[residx],
                                                         DnScaleRatio[0]))
        sht.write_row(1, cols_bd, QualityList)
        for (cls, clip_list), row_class in zip(ClipDict.items(), Rows_Class):
            rows_content = [i * len(QPs) for i in range(len(clip_list))]
            for row_cont in rows_content:
                for y in range(len(QualityList)):
                    refbr_b = xlrd.cellnameabs(row_class + row_cont + row_refst,
                                               cols[0])
                    refbr_e = xlrd.cellnameabs(row_class + row_cont + row_refst
                                               + bdstep, cols[0])
                    refq_b = xlrd.cellnameabs(row_class + row_cont + row_refst,
                                              cols[0] + 1 + y)
                    refq_e = xlrd.cellnameabs(row_class + row_cont + row_refst
                                              + bdstep, cols[0] + 1 + y)

                    testbr_b = xlrd.cellnameabs(row_class + row_cont + row_refst,
                                                cols[residx])
                    testbr_e = xlrd.cellnameabs(row_class + row_cont + row_refst
                                             + bdstep, cols[residx])
                    testq_b = xlrd.cellnameabs(row_class + row_cont + row_refst,
                                               cols[residx] + 1 + y)
                    testq_e = xlrd.cellnameabs(row_class + row_cont + row_refst
                                              + bdstep, cols[residx] + 1 + y)

                    #formula = '=bdrate(%s:%s,%s:%s,%s:%s,%s:%s)' % (
                    #refbr_b, refbr_e, refq_b, refq_e, testbr_b, testbr_e,
                    # testq_b, testq_e)
                    formula = '=bdRateExtend(%s:%s,%s:%s,%s:%s,%s:%s)'\
                              % (refbr_b, refbr_e, refq_b, refq_e, testbr_b,
                                 testbr_e, testq_b, testq_e)
                    sht.write_formula(row_class + row_cont, cols_bd + y, formula,
                                      cellformat)


def CalBDRateWithPython_OneSheet(sht, cols_bdmtrs, resultfiles, cellformat):
    row_refst = 0
    bdstep = len(QPs) - 1
    assert row_refst + bdstep < len(CvxH_WtRows)

    shtname = sht.get_name()
    rdrows = CvxH_WtRows
    rdcols = CvxH_WtCols
    for cols_bd, residx in zip(cols_bdmtrs, range(1, len(DnScaleRatio))):
        sht.write(0, cols_bd, 'BD-Rate %.2f vs. %.2f' % (DnScaleRatio[residx],
                                                         DnScaleRatio[0]))
        sht.write_row(1, cols_bd, QualityList)
        for (cls, clip_list), row_class in zip(ClipDict.items(), Rows_Class):
            rows_content = [i * len(QPs) for i in range(len(clip_list))]
            for row_cont, clip in zip(rows_content, clip_list):
                key = GetShortContentName(clip.file_name)
                for resfile in resultfiles:
                    if key in resfile:
                        rdwb = xlrd.open_workbook(resfile)
                        rdsht = rdwb.sheet_by_name(shtname)
                        break
                for y in range(len(QualityList)):
                    refbrs = rdsht.col_values(rdcols[0], rdrows[row_refst], rdrows[row_refst + bdstep] + 1)
                    refqtys = rdsht.col_values(rdcols[0] + 1 + y, rdrows[row_refst], rdrows[row_refst + bdstep] + 1)
                    testbrs = rdsht.col_values(rdcols[residx], rdrows[row_refst], rdrows[row_refst + bdstep] + 1)
                    testqtys = rdsht.col_values(rdcols[residx] + 1 + y, rdrows[row_refst], rdrows[row_refst + bdstep] + 1)
                    bdrate = BD_RATE(refbrs, refqtys, testbrs, testqtys) / 100.0
                    sht.write(row_class + row_cont, cols_bd + y, bdrate, cellformat)

def GenerateFormula_SumRows(shtname, rows, col):
    cells = ''
    for row in rows:
        location = xlrd.cellnameabs(row, col)
        cells = cells + '\'%s\'!%s,' % (shtname, location)
    cells = cells[:-1]  # remove the last ,
    formula = '=SUM(%s)/%d' % (cells, len(rows))
    return formula

def GenerateFormula_SumRows_Weighted(rows, col, weight_rows, weight_col, num):
    cells = ''
    for row, wtrow in zip(rows, weight_rows):
        location = xlrd.cellnameabs(row, col)
        weight = xlrd.cellnameabs(wtrow, weight_col)
        cells = cells + '%s * %s,' % (location, weight)
    cells = cells[:-1]  # remove the last ,
    formula = '=SUM(%s)/%d' % (cells, num)
    return formula

def WriteBitrateQtyAverageSheet(wb, rdshts, rdcols):
    avg_sht = wb.add_worksheet('Average')
    avg_sht.write(2, 0, 'Content Class')
    avg_sht.write(2, 1, 'Content Number')
    avg_sht.write(2, 2, 'QP')

    colstart = 3
    cols_res = [colstart]
    step = len(QualityList) + 1 + 1  # 1 for bitrate, 1 for interval
    colres_2nd_start = colstart + step
    step = len(upScalAlgos) * (len(QualityList) + 1) + 1  # + 1 for interval
    cols_res += [step * i + colres_2nd_start for i in range(len(DnScaleRatio) - 1)]
    step = len(QualityList) + 1  # + 1 for bitrate
    cols_upscl = [step * i for i in range(len(upScalAlgos))]
    for residx, col_res in zip(range(len(DnScaleRatio)), cols_res):
        avg_sht.write(0, col_res, 'ScalingRatio = %.2f' % (DnScaleRatio[residx]))
        if residx == 0:
            avg_sht.write(1, col_res + 1, 'None')
            avg_sht.write(2, col_res, 'Bitrate(kbps)')
            avg_sht.write_row(2, col_res + 1, QualityList)
        else:
            for dnsc, upsc, col_upscl in zip(dnScalAlgos, upScalAlgos, cols_upscl):
                avg_sht.write(1, col_res + col_upscl + 1, '%s--%s' % (dnsc, upsc))
                avg_sht.write(2, col_res + col_upscl, 'Bitrate(kbps)')
                avg_sht.write_row(2, col_res + col_upscl + 1, QualityList)

    startrow = 3
    step = len(QPs)
    rows_class_avg = [startrow + step * i for i in range(len(ClipDict))]
    totalnum_content = 0
    for (cls, clip_list), row_class, rdclassrow in zip(ClipDict.items(),
                                                      rows_class_avg,
                                                      Rows_Class):
        avg_sht.write(row_class, 0, cls)
        totalnum_content = totalnum_content + len(clip_list)
        avg_sht.write(row_class, 1, len(clip_list))
        avg_sht.write_column(row_class, 2, QPs)
        rows_content = [i * len(QPs) for i in range(len(clip_list))]

        for rdcol, col_res, residx in zip(rdcols, cols_res, range(len(DnScaleRatio))):
            for i in range(len(QPs)):
                sum_rows = [rdclassrow + row_cont + i for row_cont in rows_content]
                for col_upscl, sht in zip(cols_upscl, rdshts):
                    shtname = sht.get_name()
                    # write bitrate average formula.
                    formula = GenerateFormula_SumRows(shtname, sum_rows, rdcol)
                    avg_sht.write_formula(row_class + i, col_res + col_upscl,
                                          formula)
                    # write quality average formula
                    for j in range(len(QualityList)):
                        formula = GenerateFormula_SumRows(shtname, sum_rows,
                                                          rdcol + 1 + j)
                        avg_sht.write_formula(row_class + i,
                                              col_res + col_upscl + 1 + j,
                                              formula)

                    # for first resolution, no down and up scaling. only need
                    # one set of bitrate/quality data
                    if residx == 0:
                        break

    # write total average
    last_class_row = rows_class_avg[-1] + len(QPs) + 1  # 1 for 1 row of interval
    avg_sht.write(last_class_row, 0, 'Total')
    avg_sht.write(last_class_row, 1, totalnum_content)
    avg_sht.write_column(last_class_row, 2, QPs)
    weight_rows = [row_class for row_class in rows_class_avg]
    for col_res, residx in zip(cols_res, range(len(DnScaleRatio))):
        for i in range(len(QPs)):
            sum_rows = [row_class + i for row_class in rows_class_avg]
            for col_upscl in cols_upscl:
                # bitrate average
                formula = GenerateFormula_SumRows_Weighted(sum_rows,
                                                           col_res + col_upscl,
                                                           weight_rows, 1,
                                                           totalnum_content)
                avg_sht.write_formula(last_class_row + i, col_res + col_upscl,
                                      formula)
                # quality average
                for j in range(len(QualityList)):
                    formula = GenerateFormula_SumRows_Weighted(sum_rows,
                                                               col_res +
                                                               col_upscl + 1 + j,
                                                               weight_rows, 1,
                                                               totalnum_content)
                    avg_sht.write_formula(last_class_row + i,
                                          col_res + col_upscl + 1 + j, formula)
                # for first resolution, no down and up scaling. only need one
                # set of bitrate/quality data
                if residx == 0:
                    break

def WriteBDRateAverageSheet(wb, rdshts, rd_cols_bdmtrs, cellformat):
    # write bdrate average sheet
    bdavg_sht = wb.add_worksheet('Average_BDRate')
    bdavg_sht.write(2, 0, 'Content Class')
    bdavg_sht.write(2, 1, 'Content Number')

    startcol = 2
    startrow = 3
    colintval_scalalgo = 1
    colintval_dnscalres = 1

    step_upscl = len(QualityList) + colintval_scalalgo
    cols_upscl_bd = [step_upscl * i for i in range(len(upScalAlgos))]
    step_res = len(upScalAlgos) * step_upscl + colintval_dnscalres
    cols_res_bd = [step_res * i + startcol for i in range(len(DnScaleRatio) - 1)]
    rows_class_rdavg = [startrow + i for i in range(len(ClipDict))]

    for residx, col_res_bd in zip(range(1, len(DnScaleRatio)), cols_res_bd):
        bdavg_sht.write(0, col_res_bd, 'BD-Rate %.2f vs. %.2f'
                        % (DnScaleRatio[residx], DnScaleRatio[0]))
        for dnsc, upsc, col_upscl_bd in zip(dnScalAlgos, upScalAlgos, cols_upscl_bd):
            bdavg_sht.write(1, col_res_bd + col_upscl_bd, '%s--%s' % (dnsc, upsc))
            bdavg_sht.write_row(2, col_res_bd + col_upscl_bd, QualityList)

    totalnum_content = 0
    for (cls, clip_list), row_class, rdclassrow in zip(ClipDict.items(),
                                                      rows_class_rdavg,
                                                      Rows_Class):
        bdavg_sht.write(row_class, 0, cls)
        totalnum_content = totalnum_content + len(clip_list)
        bdavg_sht.write(row_class, 1, len(clip_list))
        rows_content = [i * len(QPs) for i in range(len(clip_list))]
        sum_rows = [rdclassrow + row_cont for row_cont in rows_content]
        for rdcol, col_res in zip(rd_cols_bdmtrs, cols_res_bd):
            # write average bd rate
            for col_upscl, sht in zip(cols_upscl_bd, rdshts):
                shtname = sht.get_name()
                for j in range(len(QualityList)):
                    formula = GenerateFormula_SumRows(shtname, sum_rows, rdcol + j)
                    bdavg_sht.write_formula(row_class, col_res + col_upscl + j,
                                            formula, cellformat)

    # write total average
    last_row = rows_class_rdavg[-1] + 1
    bdavg_sht.write(last_row, 0, 'Total')
    bdavg_sht.write(last_row, 1, totalnum_content)
    sum_rows = [row_class for row_class in rows_class_rdavg]
    for col_res in cols_res_bd:
        for col_upscl in cols_upscl_bd:
            for j in range(len(QualityList)):
                formula = GenerateFormula_SumRows_Weighted(sum_rows,
                                                           col_res + col_upscl + j,
                                                           sum_rows, 1,
                                                           totalnum_content)
                bdavg_sht.write_formula(last_row, col_res + col_upscl + j,
                                        formula, cellformat)


#######################################################################
#######################################################################
# GenerateSummaryExcelFile is to
# 1. summarize all contents convexhull results into one file
# 2. calculate average of bitrate and quality metrics for each content class
# 3. calculate BD rate across different scaling ratios for all scaling
#    algorithms in convex hull test
# 4. calcualte average BD rate for each content class
# Arguments description:
# content_paths is where test contents located, which used for generating convex
#               hull results.
# resultfiles   is a list of all convex hull RD result files generated by
#                runninging '-f convexhull'
# summary_outpath  is the folder where output summary file will be
def GenerateSumRDExcelFile(encMethod, codecName, preset, summary_outpath,
                           resultfiles, clip_list):

    global dnScalAlgos, upScalAlgos
    # find all scaling algos tested in results file,
    # IMPORTANT: expect up and down scaling algos are the same for every content
    dnScalAlgos, upScalAlgos = SweepScalingAlgosInOneResultFile(resultfiles)

    if not os.path.exists(summary_outpath):
        os.makedirs(summary_outpath)
    smfile = GetRDSummaryFileName(encMethod, codecName, preset, summary_outpath)
    wb = xlsxwriter.Workbook(smfile)

    # shts is for all scaling algorithms' convex hull test results
    shts = []
    for dnsc, upsc in zip(dnScalAlgos, upScalAlgos):
        shtname = dnsc + '--' + upsc
        sht = wb.add_worksheet(shtname)
        shts.append(sht)

    # below variables define summary file data layout format.
    # if to change them, modify CopyResultsDataToSummaryFile_Onesheet() and
    # CalcRowsCategAndContentDict() accordingly
    colstart = 3
    colInterval = 2
    rowstart = 2
    # to generate rows number of starting of each class: Rows_Class
    global ClipDict, Rows_Class
    ClipDict, Rows_Class = CalcRowsClassAndContentDict(rowstart, clip_list, len(QPs))
    # cols is column number of results files
    step = colInterval + 1 + len(QualityList)  # 1 is for bitrate
    sum_wtcols = [step * i + colstart for i in range(len(DnScaleRatio))]

    if CalcBDRateInExcel:
        wb.add_vba_project(VbaBinFile)
    cellformat = wb.add_format()
    cellformat.set_num_format('0.00%')
    #cols_bdmtrs is the column number to write the bdrate data
    step = len(QualityList) + 1
    start_col_bd = sum_wtcols[-1] + step + 1
    cols_bdmtrs = [start_col_bd + i * step for i in range(len(DnScaleRatio) - 1)]
    # -1 because first resolution is used as reference

    for sht in shts:
        CopyResultDataToSummaryFile_Onesheet(sht, sum_wtcols, resultfiles)
        # calculate bd rate in each scaling sheet
        if CalcBDRateInExcel:
            CalBDRateWithExcel_OneSheet(sht, sum_wtcols, cols_bdmtrs, cellformat)
        else:
            CalBDRateWithPython_OneSheet(sht, cols_bdmtrs, resultfiles, cellformat)

    # calculate average bitrate and quality metrics for each category and
    # write to "average" sheet
    WriteBitrateQtyAverageSheet(wb, shts, sum_wtcols)

    # calculate average bd metrics and write to a new sheet
    WriteBDRateAverageSheet(wb, shts, cols_bdmtrs, cellformat)

    wb.close()
    return smfile

def GenerateSumCvxHullExcelFile(encMethod, codecName, preset, summary_outpath,
                                resultfiles, EnablePreInterpolation = False):
    if not os.path.exists(summary_outpath):
        os.makedirs(summary_outpath)
    smfile = GetConvexHullDataSummaryFileName(encMethod, codecName, preset,
                                     summary_outpath)
    wb = xlsxwriter.Workbook(smfile)
    cvx_cols = 4
    if EnablePreInterpolation:
        cvx_cols = 6
    # shts is for all scaling algorithms' convex hull test results
    shts = []
    cols = [3 + i * cvx_cols for i in range(len(QualityList))]
    for dnsc, upsc in zip(dnScalAlgos, upScalAlgos):
        shtname = dnsc + '--' + upsc
        sht = wb.add_worksheet(shtname)
        shts.append(sht)
        # write headers
        sht.write(0, 0, 'Content Class')
        sht.write(0, 1, 'Content Name')
        sht.write(0, 2, 'Num RD Points')

        for qty, col in zip(QualityList, cols):
            sht.write(0, col,     'Resolution')
            sht.write(0, col + 1, 'QP')
            sht.write(0, col + 2, 'Bitrate(kbps)')
            sht.write(0, col + 3,  qty)
            if EnablePreInterpolation:
                sht.write(0, col + 4, 'Int_Bitrate(kbps)')
                sht.write(0, col + 5, 'Int_' + qty)

        # copy convexhull data from each content's result file to corresponding
        # location in summary excel file
        row = 1
        rdcolstart = CvxHDataStartCol + 1
        for (cls, clip_list) in ClipDict.items():
            sht.write(row, 0, cls)
            for clip in clip_list:
                key = GetShortContentName(clip.file_name)
                sht.write(row, 1, key)
                for resfile in resultfiles:
                    if key in resfile:
                        rdwb = xlrd.open_workbook(resfile)
                        rdsht = rdwb.sheet_by_name(shtname)
                        maxNumQty = 0; maxNumIntQty = 0
                        for rdrow, col in zip(CvxHDataRows, cols):
                            qtys = []; brs = []; qps = []; ress = []
                            int_qtys = []; int_brs = []
                            numQty = 0
                            for qty in rdsht.row_values(rdrow)[rdcolstart:]:
                                if qty == '':
                                    break
                                else:
                                    qtys.append(qty)
                                    numQty = numQty + 1
                            maxNumQty = max(maxNumQty, numQty)

                            for br in rdsht.row_values(rdrow + 1)[rdcolstart:]:
                                if br == '':
                                    break
                                else:
                                    brs.append(br)
                            for qp in rdsht.row_values(rdrow + 2)[rdcolstart:]:
                                if qp == '':
                                    break
                                else:
                                    qps.append(qp)
                            for res in rdsht.row_values(rdrow + 3)[rdcolstart:]:
                                if res == '':
                                    break
                                else:
                                    ress.append(res)
                            if EnablePreInterpolation:
                                numQty = 0
                                for qty in rdsht.row_values(rdrow + 4)[
                                           rdcolstart:]:
                                    if qty == '':
                                        break
                                    else:
                                        int_qtys.append(qty)
                                        numQty = numQty + 1
                                maxNumIntQty = max(maxNumIntQty, numQty)
                                for br in rdsht.row_values(rdrow + 5)[rdcolstart:]:
                                    if br == '':
                                        break
                                    else:
                                        int_brs.append(br)

                            sht.write_column(row, col, ress)
                            sht.write_column(row, col + 1, qps)
                            sht.write_column(row, col + 2, brs)
                            sht.write_column(row, col + 3, qtys)
                            if EnablePreInterpolation:
                                sht.write_column(row, col + 4, int_brs)
                                sht.write_column(row, col + 5, int_qtys)

                        sht.write(row, 2, max(maxNumQty, maxNumIntQty))
                        row = row + max(maxNumQty, maxNumIntQty)
                        break

    wb.close()
    return smfile
