import com.gridnine.xtrip.common.l10n.model.LocaleHelper
import com.gridnine.xtrip.common.model.EntityReference
import com.gridnine.xtrip.common.model.booking.OperationBatch
import com.gridnine.xtrip.common.model.dict.CodeSystem
import com.gridnine.xtrip.common.model.dict.GdsName
import com.gridnine.xtrip.common.model.entity.EntityStorage
import com.gridnine.xtrip.common.model.profile.Address
import com.gridnine.xtrip.common.model.profile.GdsReference
import com.gridnine.xtrip.common.model.profile.Person
import com.gridnine.xtrip.common.model.profile.SalesPoint
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportParameters
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket
import com.gridnine.xtrip.common.util.CollectionUtil
import com.gridnine.xtrip.common.util.MiscUtil
import com.gridnine.xtrip.common.util.TextUtil

import java.text.SimpleDateFormat


createStyle(name: "left", h_alignment: "LEFT")
createStyle(name: "right", h_alignment: "RIGHT")
createStyle(name: "center", h_alignment: "CENTER")
createStyle(name: "left-bold", h_alignment: "LEFT", fontBold : true)
createStyle(name: "right-bold", h_alignment: "RIGHT", fontBold : true)
createStyle(name: "center-bold", h_alignment: "CENTER", fontBold : true)
createStyle(name: "left-bold-border", h_alignment: "LEFT", fontBold : true,
        leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "right-bold-border", h_alignment: "RIGHT", fontBold : true,
        leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-bold-border", h_alignment: "CENTER", fontBold : true,
        leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "left-border", h_alignment: "LEFT", leftBorder:'THIN', rightBorder:'THIN',
        topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "right-border", h_alignment: "RIGHT", leftBorder:'THIN', rightBorder:'THIN',
        topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-border", h_alignment: "CENTER", leftBorder:'THIN', rightBorder:'THIN',
        topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "dateDataBold", format: 'm/d/yy', parent: 'left-bold-border')
createStyle(name: "dateData", format: 'm/d/yy', parent: 'center-border')
createStyle(name: 'numberData', format: '#,##0.00', parent: 'center-border')

class Formula {
    String formula
    Formula(){}
    Formula(String formula) {
        this.formula = formula
    }

    static Formula getSumFormulaByRow (def start, def 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(Object 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, 'center-border')
        }
    } else {
        text('', 'center-border')
    }
}

def printEmptyBorderedCell() {
    text('', 'left-bold-border')
    nextColumn()
}

def printColumnHeader(def str, def width) {
    columnWidth(width)
    text(str, 'center-border')
    nextColumn()
}

def printHead(AirTicketsTemplateReportParameters airTicketParams) {
    rowHeight(15)
    text('Наименование/код Агента:', 'center-bold', 3, 1)
    4.times {nextColumn()}
    text(airTicketParams?.agency?.caption + '/' + parameters['agency_code'], 'center-bold', 3, 1)
    nextRow()
    rowHeight(15)
    2.times {nextColumn()}
    text('Реестр к счету-фактуре №', 'center-bold', 13, 1)
    nextRow()
    rowHeight(15)
    nextColumn()
    text('воинских перевозочных документов (ВПД), на основании которых оформлены авиабилеты', 'center-bold', 15, 1)
    nextRow()
    rowHeight(15)
    nextColumn()
    SimpleDateFormat sdf = new SimpleDateFormat('dd.MM.yyyy')
    text('за период ' + sdf.format(airTicketParams.periodBegin) +
            ' ' + sdf.format(airTicketParams.periodEnd), 'center-bold', 14, 1)
    2.times {nextRow()}
    rowHeight(30)
    text('Организация\n клиент:', 'center-bold', 2, 1)
    4.times {nextColumn()}
    text('МИНИСТЕРСТВО ОБОРОНЫ РФ', 'center-bold', 3, 1)
    nextRow()
    rowHeight(15)
    text('Перевозчик:', 'center-bold', 2, 1)
    4.times {nextColumn()}
    text('АО "АВИАКОМПАНИЯ "ЯКУТИЯ"', 'center-bold', 3, 1)
    nextRow()
    rowHeight(15)
    text('Валюта', 'center-bold', 2, 1)
    4.times {nextColumn()}
    text('РУБ.', 'center-bold')
    2.times {nextRow()}
}

def printTitle() {
    rowHeight(70)
    printColumnHeader('№ п/п', 5)
    printColumnHeader('Личный номер кассира', 12)
    printColumnHeader('Пункт оформления перевозочного документа', 15)
    printColumnHeader('Серия,номер перевозочного документа', 15)
    printColumnHeader('Серия, номер воинского требования', 15)
    printColumnHeader('Дата оформле-ния перевозочного документа', 15)
    printColumnHeader('Дата перевозки по перевозочному документу', 18)
    printColumnHeader('Перевозчик (код)', 12)
    printColumnHeader('Номер рейса', 12)
    printColumnHeader('Аэропорт отправления', 12)
    printColumnHeader('Аэропорт назначения', 12)
    printColumnHeader('ФИО пассажира, возраст  детей', 20)
    printColumnHeader('Наименование, серия номер документа, удостоверяющего личность', 15)
    printColumnHeader('Вид тарифа', 12)
    printColumnHeader('Сумма к оплате (в рублях)', 12)
    printColumnHeader('Корретировка суммы (в рублях)', 12)
    printColumnHeader('Основание корректировки суммы', 12)
    nextRow()
}

def printTickets() {

    def getSalesPointAddress = {EntityReference<SalesPoint> ref ->
        SalesPoint salesPoint = EntityStorage.get().resolve(ref)?.entity
        List<Address> addresses = salesPoint?.addresses
        String result = ''
        if(CollectionUtil.isNotEmpty(addresses)) {
            result = addresses.get(0)?.city?.toString(LocaleHelper.RU_LOCALE)
        }
        return result
    }

    def agentCode = { EntityReference<Person> agentRef ->
        String result = ""
        Person agent = EntityStorage.get().resolve(agentRef)?.entity
        if (agent != null) {
            for (GdsReference ref : agent.gdsReferences) {
                if (ref.gdsName == GdsName.SIRENA
                        && TextUtil.nonBlank(ref.reference)) {
                    result = ref.reference
                    break;
                }
            }
        }
        return result
    }

    def fillTable = { AirTicketsTemplateReportTicket ticket, int index, boolean negate ->
        number(index, 'center-border')
        nextColumn()
        cellFill(agentCode(ticket.agent))
        nextColumn()
        cellFill(getSalesPointAddress(ticket.salesPoint))
        nextColumn()
        cellFill(ticket.validatingCarrierNumber + ' ' + ticket.ticketNumber)
        nextColumn()
        cellFill(ticket.militaryClaimNumber)
        nextColumn()
        cellFill(ticket.issueDate)
        nextColumn()
        cellFill(ticket.departureDate)
        nextColumn()
        cellFill('ЯК')
        nextColumn()
        cellFill(CollectionUtil.collectionToString(ticket.flightNumbers, ' ', true))
        nextColumn()
        cellFill(ticket.departureLocationCodes.get(CodeSystem.CRT.name()))
        nextColumn()
        cellFill(ticket.arriveLocationCodes.get(CodeSystem.CRT.name()))
        nextColumn()
        cellFill(ticket.travellerName)
        nextColumn()
        cellFill(ticket.travellerPassportNumber)
        nextColumn()
        cellFill(ticket.fareBasisLine)
        nextColumn()
        cellFill(negate ? MiscUtil.negate(ticket.equivalentFare) : ticket.equivalentFare)
        nextColumn()
        cellFill('')
        nextColumn()
        cellFill('')
        nextRow()
    }

    List<AirTicketsTemplateReportTicket> sells = new ArrayList<>()
    List<AirTicketsTemplateReportTicket> refunds = new ArrayList<>()
    allTickets.each { AirTicketsTemplateReportTicket ticket ->
        if (ticket.operationBatch == OperationBatch.SELL) {
            sells.add(ticket)
        } else if (ticket.operationBatch == OperationBatch.REFUND) {
            refunds.add(ticket)
        }
    }
    rowHeight(30)
    text('Продажа:', 'left-bold-border', 14, 1)
    14.times {nextColumn()}
    3.times {printEmptyBorderedCell()}
    nextRow()
    int sellIndex = 0
    sells.each { AirTicketsTemplateReportTicket ticket ->
        fillTable(ticket, ++sellIndex, false)
    }
    13.times {printEmptyBorderedCell()}
    cellFill('Итого Продажа')
    nextColumn()
    if (!sells.isEmpty()) {
        cellFill(Formula.getSumFormulaByRow(cellIndex(-sells.size(), 0), cellIndex(-1, 0)))
    } else  {
        cellFill(BigDecimal.ZERO)
    }
    nextColumn()
    2.times {printEmptyBorderedCell()}
    nextRow()
    text('Возврат:', 'left-bold-border', 14, 1)
    14.times {nextColumn()}
    3.times {printEmptyBorderedCell()}
    nextRow()
    int refIndex = 0
    refunds.each { AirTicketsTemplateReportTicket ticket ->
        fillTable(ticket, ++refIndex, true)
    }
    13.times {printEmptyBorderedCell()}
    cellFill('Итого Возврат')
    nextColumn()
    if (!refunds.isEmpty()) {
        cellFill(Formula.getSumFormulaByRow(cellIndex(-refunds.size(), 0), cellIndex(-1, 0)))
    } else {
        cellFill(BigDecimal.ZERO)
    }
    nextColumn()
    2.times {printEmptyBorderedCell()}
    nextRow()
    13.times {printEmptyBorderedCell()}
    cellFill('Всего:')
    nextColumn()
    if (!refunds.isEmpty()) {
        cellFill(new Formula(cellIndex((-3 - refunds.size()), 0) + "+" + cellIndex(-1, 0)))
    } else {
        cellFill(BigDecimal.ZERO)
    }
    nextColumn()
    2.times {printEmptyBorderedCell()}
    nextRow()
    nextColumn()
    text('ИТОГО ВОИНСКИХ ПЕРЕВОЗОЧНЫХ ДОКУМЕНТОВ ' + (sells.size() + refunds.size()) + ' ШТ.', 'center', 7, 1)
    nextRow()
}

def printEnd() {
    2.times {nextRow()}
    5.times {nextColumn()}
    text('Генеральный директор', 'center', 3, 1)
    3.times {nextColumn()}
    text(parameters['ceo_name'], 'center', 3, 1)
    nextRow()
    5.times {nextColumn()}
    text('Главных бухгалтер', 'center', 3, 1)
    3.times {nextColumn()}
    text(parameters['chief_accountant_name'], 'center', 3, 1)
}

page{'Реестр по ВПД МО'} {
    AirTicketsTemplateReportParameters airTicketParams = parameters.params
    printHead(airTicketParams)
    printTitle()
    printTickets()
    printEnd()
}