
import com.gridnine.xtrip.common.model.EntityContainer
import com.gridnine.xtrip.common.model.EntityReference
import com.gridnine.xtrip.common.model.booking.OperationBatch
import com.gridnine.xtrip.common.model.booking.air.Tax
import com.gridnine.xtrip.common.model.dict.CurrencyInfo
import com.gridnine.xtrip.common.model.dict.MCOCategory
import com.gridnine.xtrip.common.model.dict.ProductCategory
import com.gridnine.xtrip.common.model.entity.EntityStorage
import com.gridnine.xtrip.common.model.helpers.DictHelper
import com.gridnine.xtrip.common.model.profile.Organization
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportParameters
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket
import com.gridnine.xtrip.common.util.MiscUtil
import com.gridnine.xtrip.common.util.TextUtil

//CREATING STYLES
createStyle(name: 'baseStyle', fontBold: true,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:12)
createStyle(name: 'bigHeader', parent: 'baseStyle', fontHeight:18)
createStyle(name: 'smallHeader', parent:'baseStyle', fontHeight:8, h_alignment: 'RIGHT')
createStyle(name: 'smallHeaderCenter', parent: 'smallHeader', h_alignment: 'CENTER')
createStyle(name: 'tableHeader', parent: 'baseStyle', fontHeight:8, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM')
createStyle(name: 'tableContent', parent: 'baseStyle', fontHeight:8, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN')
createStyle(name: 'style', fontBold: false, fontHeight: 11, parent: 'baseStyle')
createStyle(name: 'textData', parent: 'tableContent', fontBold: false)
createStyle(name: 'textDataBold', parent: 'tableContent')
createStyle(name: 'dateData', format: 'm/d/yy', parent: 'tableContent', fontBold: false)
createStyle(name: 'dateDataBold', format: 'm/d/yy', parent: 'tableContent')
createStyle(name: 'numberData', format: '#,##0.00', parent: 'tableContent', fontBold: false)
createStyle(name: 'emptyNumberData', parent: 'tableContent', fontBold: false)
createStyle(name: 'numberDataBold', format: '#,##0.00', parent: 'tableContent')

//ADDITIONAL FUNCTIONS
class Formula{
    String formula
    Formula(){}
    Formula(String formula) {
        this.formula = formula
    }

    static Formula getSumFormulaByRow(String start, String end){
        return new Formula('SUM(' + start + ':' + end + ')')
    }
    static Formula getSumFormulaByCell(String... index){
        def formula = ''
        for (int i = 0; i < index.size(); i++) {
            if (i == 0) {
                formula += index[i]
            } else {
                formula += ',' + index[i]
            }
        }
        return new Formula('SUM(' + formula + ')')
    }
}

def cellFill = { value ->
    if (value != null) {
        if (value instanceof Number) {
            number(value,'numberData')
        } else if (value instanceof Date) {
            date(value,'dateData')
        } else if (value instanceof Formula) {
            formula(value.formula,'numberData')
        } else {
            text(value, 'textData')
        }
    }
}

def cellFillBold = { value ->
    if (value != null) {
        if (value instanceof Number) {
            number(value,'numberDataBold')
        } else if (value instanceof Date) {
            date(value,'dateDataBold')
        } else {
            text(value, 'textDataBold')
        }
    }
}

def getOrganization = { EntityReference<Organization> erO ->
    EntityContainer<Organization> ecO = EntityStorage.get().resolve(erO)
    return ecO?.entity
}

def getCurrencyInfo = { String curCode->
    Set<CurrencyInfo> currencyInfo = DictHelper.getDictionaryItemsByCode(CurrencyInfo.class, curCode)
    String result = ''
    if(currencyInfo.size() == 1) {
        for(CurrencyInfo info: currencyInfo) {
            result = info.getCode() + ' ' + info.toString(Locale.ENGLISH)
        }
    }
    return result
}

def reportHeader = {EntityReference<Organization> orgRef, String currencyCode ->
    def scw = 12
    Organization org = getOrganization(orgRef)
    def orgName = ''
    String currencyInfo = getCurrencyInfo(currencyCode)
    if(org != null) {
        orgName = org.fullName.toString()
    }


    columnWidth(scw)
    nextColumn()
    columnWidth(4*scw)
    nextColumn()
    columnWidth(2.5*scw)
    text('Приложение №', 'smallHeader', 2, 1)
    nextColumn()
    columnWidth(2.5*scw)
    nextRow()
    2.times {nextColumn()}
    text('к  Агентскому соглашению о продаже воздушных перевозок', 'smallHeader', 2, 1)
    nextRow()
    2.times {nextColumn()}
    text('на электронных билетах Перевозчика АО "Ред Вингс', 'smallHeader', 2, 1)
    nextRow()
    2.times {nextColumn()}
    text('', 'smallHeader', 2, 1)
    2.times {nextRow()}
    rowHeight(2*scw)
    text('СВОДНЫЙ ОТЧЁТ О ПРОДАЖЕ ПЕРЕВОЗОК', 'bigHeader', 3, 1)
    nextRow()
    rowHeight(scw)
    nextRow()
    text('Агент', 'baseStyle')
    nextColumn()
    text(orgName, 'baseStyle')
    nextColumn()
    text('Период продажи', 'baseStyle')
    nextColumn()
    text(parameters.REPORT_PERIOD, 'baseStyle')
    2.times {nextRow()}
    text('Валюта отчета', 'smallHeader')
    nextColumn()
    text(currencyInfo, 'smallHeader')
    nextColumn()
    text('Сальдо на начало периода', 'smallHeader')
    nextColumn()
    text('', 'smallHeader')
    nextRow()
}

def reportEnd = {
    2.times {nextColumn()}
    text('Сальдо на конец периода', 'smallHeader')
    nextColumn()
    text('', 'smallHeaderCenter')
    2.times {nextRow()}
    nextColumn()
    text('Генеральный директор', 'smallHeader')
    nextColumn()
    text('____________________', 'smallHeaderCenter')
    nextColumn()
    text('', 'smallHeaderCenter')
    nextRow()
    2.times {nextColumn()}
    text('(подпись)', 'smallHeaderCenter')
    nextRow()
    3.times {nextColumn()}
    text('М.П.', 'smallHeaderCenter')
    nextRow()
    nextColumn()
    text('Главный бухгалтер', 'smallHeader')
    nextColumn()
    text('____________________', 'smallHeaderCenter')
    nextRow()
    2.times {nextColumn()}
    text('(подпись)', 'smallHeaderCenter')
    nextRow()
    nextColumn()
    text('Исполнитель: ________________', 'smallHeaderCenter')
    nextRow()
    nextColumn()
    text('тел.: ', 'smallHeaderCenter')
}

def tableHeader = {
    text('№ п/п', 'tableHeader')
    nextColumn()
    text('Наименование', 'tableHeader')
    nextColumn()
    text('Сумма', 'tableHeader')
    nextColumn()
    text('Примечание', 'tableHeader')
    nextRow()
    text('1', 'tableHeader')
    nextColumn()
    text('2', 'tableHeader')
    nextColumn()
    text('3', 'tableHeader')
    nextColumn()
    text('4', 'tableHeader')
    nextRow()
}

def makeCalculation = {
    def result = []

    def sellTariff = BigDecimal.ZERO
    def fuelTaxSell = BigDecimal.ZERO
    def agsTaxSell = BigDecimal.ZERO
    def saTaxSell = BigDecimal.ZERO
    def luggageSell = BigDecimal.ZERO
    def penalty = BigDecimal.ZERO

    def refundTariff = BigDecimal.ZERO
    def fuelTaxRefund = BigDecimal.ZERO
    def agsTaxRefund = BigDecimal.ZERO
    def saTaxRefund = BigDecimal.ZERO
    def luggageRefund = BigDecimal.ZERO

    def agencyRewardSell = BigDecimal.ZERO
    def agencyRewardRefund = BigDecimal.ZERO
    def agencyRewardLuggage = BigDecimal.ZERO

    allTickets.each {  AirTicketsTemplateReportTicket ticket ->
        if (ticket.operationBatch == OperationBatch.SELL) {
            if (ticket.productCategory == ProductCategory.EXCESS_BAGAGE
                    || ticket.mcoCategory == MCOCategory.EXCESS_LUGGAGE) {
                luggageSell = MiscUtil.sum(luggageSell, ticket.equivalentFare)
                agencyRewardLuggage = MiscUtil.sum(agencyRewardLuggage, ticket.vendorCommissionValue)
            } else {
                sellTariff = MiscUtil.sum(sellTariff, ticket.equivalentFare)
                agencyRewardSell = MiscUtil.sum(agencyRewardSell, ticket.vendorCommissionValue)
            }
            ticket.taxes.each { Tax tax ->
                if (TextUtil.isSame(tax.code, 'AGS')) {
                    agsTaxSell = MiscUtil.sum(agsTaxSell, tax.equivalentAmount)
                }
            }
            fuelTaxSell = MiscUtil.sum(fuelTaxSell, ticket.fuelChargeAmount)
            penalty = MiscUtil.sum(penalty, ticket.penalty)
        } else if (ticket.operationBatch == OperationBatch.REFUND) {
            if (ticket.productCategory == ProductCategory.EXCESS_BAGAGE
                    || ticket.mcoCategory == MCOCategory.EXCESS_LUGGAGE) {
                luggageRefund = MiscUtil.sum(luggageRefund, ticket.equivalentFare)
            } else {
                refundTariff = MiscUtil.sum(refundTariff, ticket.equivalentFare)
            }
            ticket.taxes.each { Tax tax ->
                if (TextUtil.isSame(tax.code, 'AGS')) {
                    agsTaxRefund = MiscUtil.sum(agsTaxRefund, tax.equivalentAmount)
                }
            }
            agencyRewardRefund = MiscUtil.sum(agencyRewardRefund, ticket.vendorCommissionValue)
            fuelTaxRefund = MiscUtil.sum(fuelTaxRefund, ticket.fuelChargeAmount)
        } else if (ticket.operationBatch == OperationBatch.EXCHANGE) {
            //TODO exchanges
        } else if (ticket.operationBatch == OperationBatch.VOID) {
            //TODO voids
        }
    }

    result.add(sellTariff)          //0
    result.add(fuelTaxSell)         //1
    result.add(agsTaxSell)          //2
    result.add(saTaxSell)           //3
    result.add(luggageSell)         //4
    result.add(penalty)             //5
    result.add(refundTariff)        //6
    result.add(fuelTaxRefund)       //7
    result.add(agsTaxRefund)        //8
    result.add(saTaxRefund)         //9
    result.add(luggageRefund)       //10
    result.add(agencyRewardSell)    //11
    result.add(agencyRewardRefund)  //12
    result.add(agencyRewardLuggage) //13

    return result
}

def fillTableResult = {

    def table = []
    def sumTable = makeCalculation()

    table.add(['1', 'Продажа по АО "РЕД ВИНГС"', '', ''])
    table.add(['1.1', 'Тариф', sumTable[0], ''])
    table.add(['1.2', 'Топливный сбор ', sumTable[1], ''])
    table.add(['1.3', 'АГС ', sumTable[2], ''])
    table.add(['1.4', 'Такса SA', sumTable[3], ''])
    table.add(['1.5', 'Багаж', sumTable[4], ''])
    table.add(['1.6', 'Выбор места', '', ''])
    table.add(['1.7', 'Дополнительные услуги', '', ''])
    table.add(['1.8', 'Командирская почта', '', ''])
    table.add(['1.9', 'Штраф', sumTable[5], ''])
    table.add(['2', 'Возврат по АО "РЕД ВИНГС"', '', ''])
    table.add(['2.1', 'Возврат тарифа', sumTable[6], ''])
    table.add(['2.2', 'Возврат Топливного сбора', sumTable[7], ''])
    table.add(['2.3', 'Возврат АГС', sumTable[8], ''])
    table.add(['2.4', 'Возврат такса SА', sumTable[9], ''])
    table.add(['2.5', 'Возврат места', '', ''])
    table.add(['2.6', 'Возврат багажа', sumTable[10], ''])
    table.add(['3', 'Расчеты по претензиям ', '', ''])
    table.add(['3.1', 'Начислено', '', ''])
    table.add(['3.2', 'Удержано', '', ''])
    table.add(['4', 'Перечислено', '', ''])
    table.add(['4.1', 'Перечислено ', '', ''])
    table.add(['4.2', '', '', ''])
    table.add(['5', 'Итого начислено', '', ''])
    table.add(['6', 'Агентское вознаграждение     ', '', ''])
    table.add(['6.1', 'По продаже а/б', sumTable[11], ''])
    table.add(['6.2', 'По продаже багажа', sumTable[13], ''])
    table.add(['6.3', 'По продаже места', '', ''])
    table.add(['6.4', 'Агентское вознаграждение   при возврате', sumTable[12], ''])
    table.add(['7', 'Всего к перечислению', '', ''])

    return table
}

def tableBody = {
    def table = fillTableResult()

    table.each { row->
        row.each {
            cellFill(it)
            nextColumn()
        }
        nextRow()
    }
}

def reportBody = {
    tableHeader()
    tableBody()
}

page{'Consolidated report'} {
    warn 'report version = ' + '0.1.0'

    AirTicketsTemplateReportParameters airTicketParams = parameters.params
    String currencyCode = parameters.currency
    EntityReference<Organization> orgRef = airTicketParams.agency

    reportHeader(orgRef, currencyCode)
    reportBody()
    reportEnd()
}