import com.gridnine.xtrip.common.model.booking.OperationBatch
import com.gridnine.xtrip.common.model.dict.CodeSystem
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportParameters
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket
import com.gridnine.xtrip.common.util.CollectionUtil

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 printColumnHeader(def str, def width) {
    columnWidth(width)
    text(str, 'center-bold-border')
    nextColumn()
}

def printColumnHeaderNumber(def num) {
    number(num, 'center-bold-border')
    nextColumn()
}

def printHead(def header) {
    AirTicketsTemplateReportParameters airTicketParams = parameters.params
    nextRow()
    rowHeight(30)
    nextColumn()
    text(header, 'center-bold', 14, 1)
    nextRow()
    rowHeight(15)
    nextColumn()
    SimpleDateFormat sdf = new SimpleDateFormat('dd.MM.yyyy')
    text('за период с ' + sdf.format(airTicketParams.periodBegin) + ' по ' +
            sdf.format(airTicketParams.periodEnd), 'left', 14, 1)
    nextRow()
    rowHeight(15)
    nextColumn()
    text('Перевозчик: ЯК', 'left', 14, 1)
    nextRow()
}

def printTitle() {
    rowHeight(70)
    nextColumn()
    printColumnHeader('№ п/п', 8)
    printColumnHeader('Серия. номер перевозочного документа', 18)
    printColumnHeader('Дата оформления перевозочного документа', 15)
    printColumnHeader('Дата перевозчки по перевозочному документу', 15)
    printColumnHeader('Номер рейса', 8)
    printColumnHeader('Аэропорт отправления', 10)
    printColumnHeader('Аэропорт назначения', 10)
    printColumnHeader('Фамилия, имя, отчество пассажира', 25)
    printColumnHeader('Паспорт/свидетельство о рождении', 15)
    printColumnHeader('Категория пассажира', 8)
    printColumnHeader('Вид тарифа', 12)
    printColumnHeader('Величина тарифа, руб.', 12)
    printColumnHeader('Дата рождения пассажира', 12)
    printColumnHeader('Код АВС', 10)
    nextRow()
    rowHeight(15)
    nextColumn()
    int i = 0
    14.times {
        printColumnHeaderNumber(++i)
    }
    nextRow()
    rowHeight(30)
}

def fillRow(AirTicketsTemplateReportTicket ticket, int num) {

    nextColumn()
    number(num, 'center-border')
    nextColumn()
    cellFill(ticket.validatingCarrierNumber + ' ' + ticket.ticketNumber)
    nextColumn()
    cellFill(ticket.issueDate)
    nextColumn()
    cellFill(ticket.departureDate)
    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.travellerType.code)
    nextColumn()
    cellFill(ticket.fareBasisLine)
    nextColumn()
    cellFill(ticket.equivalentFare)
    nextColumn()
    cellFill(ticket.travellerBirthday)
    nextColumn()
    cellFill('')
    nextRow()
}

def printTickets(List<AirTicketsTemplateReportTicket> tickets) {
    List<AirTicketsTemplateReportTicket> sells = new ArrayList<>()
    List<AirTicketsTemplateReportTicket> refunds = new ArrayList<>()
    tickets.each {AirTicketsTemplateReportTicket ticket->
        switch (ticket.operationBatch) {
            case OperationBatch.SELL :
                sells.add(ticket)
                break
            case OperationBatch.REFUND :
                refunds.add(ticket)
                break
        }
    }
    int sellsCount = 0
    sells.each {AirTicketsTemplateReportTicket ticket->
        fillRow(ticket, ++sellsCount)
    }
    if (sellsCount > 0) {
        printEnd(sellsCount, OperationBatch.SELL)
    }
    int refsCount = 0
    refunds.each {AirTicketsTemplateReportTicket ticket->
        fillRow(ticket, ++refsCount)
    }
    if(refsCount > 0) {
        printEnd(refsCount, OperationBatch.REFUND)
    }
}

def prepareAndPrintTickets() {
    List<AirTicketsTemplateReportTicket> youthSeniorTickets = new ArrayList<>()
    List<AirTicketsTemplateReportTicket> disabledPersonTickets = new ArrayList<>()
    List<AirTicketsTemplateReportTicket> oceanTariffTickets = new ArrayList<>()
    allTickets.each{AirTicketsTemplateReportTicket ticket ->
        def fareBasisLine = ticket.fareBasisLine
        if(fareBasisLine){
            if(fareBasisLine.startsWith("YSUBZZ") || fareBasisLine.startsWith("YSUBCD")) {
                youthSeniorTickets.add(ticket)
            }else if(fareBasisLine.startsWith("YSUBSB")){
                disabledPersonTickets.add(ticket)
            } else if(fareBasisLine.startsWith("YSUBVOW")) {
                oceanTariffTickets.add(ticket)
            }
        }
    }

    printHead('Реестр продаж воздушных перевозок по специальному тарифу гражданам РФ в возрасте до 23 лет,\n'+
           ' а также гражданам РФ пенсионного возраста с Дальнего Востока в европейскую часть страны и в обратном направлении.')
    printTitle()
    printTickets(youthSeniorTickets)
    printHead('Реестр продаж воздушных перевозок по специальному тарифу гражданам РФ - инвалидам 1 группы,\n'+
            ' а также лицам, сопровождающим детей-инвалидов с Дальнего Востока в европейскую часть страны и в обратном направлении.')
    printTitle()
    printTickets(disabledPersonTickets)
    printHead('Реестр продаж воздушных перевозок по специальному тарифу ВДЦ "ОКЕАН"\n'+
            ' с Дальнего Востока в европейскую часть страны и в обратном направлении.')
    printTitle()
    printTickets(oceanTariffTickets)
}

def printEnd(int ticketsCount, OperationBatch batch) {
    nextColumn()
    if(batch == OperationBatch.SELL) {
        text('Продажа ИТОГО: ' + ticketsCount, 'center-border-bold', 2, 1)
    } else if(batch == OperationBatch.REFUND) {
        text('Возврат ИТОГО: ' + ticketsCount, 'center-border-bold', 2, 1)
    }
    2.times {nextColumn()}
    text('', 'center-border-bold', 9, 1)
    9.times {nextColumn()}
    if(ticketsCount > 0) {
        cellFill(Formula.getSumFormulaByRow(cellIndex(-ticketsCount, 0), cellIndex(-1, 0)))
    } else {
        cellFill(BigDecimal.ZERO)
    }
    nextColumn()
    text('', 'center-border-bold', 2, 1)
    nextRow()
}

page{'Реестр по субсидированным перевозкам'} {
    prepareAndPrintTickets()
}