import java.util.List;
import java.util.Locale;

import com.gridnine.xtrip.common.Environment;
import com.gridnine.xtrip.common.l10n.model.LocaleHelper;
import com.gridnine.xtrip.common.model.EntityContainer;
import com.gridnine.xtrip.common.model.dict.CodeSystem;
import com.gridnine.xtrip.common.model.dict.GeoLocation;
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket;
import com.gridnine.xtrip.common.model.helpers.DictHelper;
import com.gridnine.xtrip.common.search.SearchCriterion;
import com.gridnine.xtrip.common.search.SearchQuery;
import com.gridnine.xtrip.common.util.MiscUtil;
import com.gridnine.xtrip.common.util.TextUtil;
import com.gridnine.xtrip.common.model.booking.air.Product;
import com.gridnine.xtrip.common.model.booking.BookingFile;
import com.gridnine.xtrip.common.model.booking.BookingFileIndex;
import com.gridnine.xtrip.common.model.booking.Traveller;
import com.gridnine.xtrip.common.model.booking.ProductIndex;
import com.gridnine.xtrip.common.model.profile.Passport;
import com.gridnine.xtrip.common.model.entity.EntityStorage;
import com.gridnine.xtrip.server.db.storage.common.StorageHelper;
import com.gridnine.xtrip.common.model.dict.Gender;
import com.gridnine.xtrip.common.model.booking.OperationBatch;
import com.gridnine.xtrip.common.model.helpers.AirProductHelper;
import com.gridnine.xtrip.common.model.helpers.ProfileHelper;
import com.gridnine.xtrip.common.model.helpers.DictHelper;
import com.gridnine.xtrip.common.model.booking.PassengerType;
import com.gridnine.xtrip.common.model.booking.PassengerTypeValue;
import com.gridnine.xtrip.common.model.profile.SalesPoint;
import com.gridnine.xtrip.common.model.profile.Address;
import com.gridnine.xtrip.common.model.helpers.DictHelper;
import com.gridnine.xtrip.common.model.dict.AddressType;
import com.gridnine.xtrip.common.model.dict.DictionaryCache;
import com.gridnine.xtrip.common.model.dict.DictionaryReference;
import com.gridnine.xtrip.common.model.dict.GeoLocation;
import com.gridnine.xtrip.common.model.dict.CodeSystem;

// Styles
createStyle(name: 'title', h_alignment: 'CENTER', v_alignment: 'CENTER')
createStyle(name: 'titleH1', fontHeight: 14, parent: 'title')
createStyle(name: 'titleH2', fontHeight: 9, parent: 'title')
createStyle(name: 'titleH3', fontHeight: 7, parent: 'title')
createStyle(name: 'header', h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight: 7)
createStyle(name: 'columnHeader', parent: 'header')
createStyle(name: 'rowHeader', parent: 'header')
createStyle(name: 'data', h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight: 7)
createStyle(name: 'dataText', parent: 'data')
createStyle(name: 'dataDate', format: 'm/d/yy', parent: 'data')
createStyle(name: 'dataNumber', h_alignment: 'RIGHT', format: '#,##0.00', parent: 'data')
createStyle(name: 'wrap', wrapText: true)
createStyle(name: 'ahl', h_alignment: 'LEFT')
createStyle(name: 'ahc', h_alignment: 'CENTER')
createStyle(name: 'ahr', h_alignment: 'RIGHT')
createStyle(name: 'avt', v_alignment: 'TOP')
createStyle(name: 'avc', v_alignment: 'CENTER')
createStyle(name: 'avb', v_alignment: 'BOTTOM')
createStyle(name: 'aac', h_alignment: 'CENTER', v_alignment: 'CENTER')
createStyle(name: 'bold', fontBold: true)
createStyle(name: 'italic', fontItalic: true)
createStyle(name: 'bt', topBorder: 'THIN')
createStyle(name: 'bl', leftBorder: 'THIN')
createStyle(name: 'bb', bottomBorder: 'THIN')
createStyle(name: 'br', rightBorder: 'THIN')
createStyle(name: 'ba', topBorder: 'THIN', leftBorder: 'THIN', bottomBorder: 'THIN', rightBorder: 'THIN')
createStyle(name: 'grey25', foreground: 'GREY_25_PERCENT')
createStyle(name: 'locked', locked: true)

// Properties
def periodBeginParameter = parameters['key-report-params']?.periodBegin
def periodEndParameter = parameters['key-report-params']?.periodEnd
def supplierParameter = parameters['key-report-params']?.supplier
def agencyParameter = parameters['key-report-params']?.agency

// Closures
def agencyName = {

    def agency = EntityStorage.get().resolve(agencyParameter)?.entity
    return agency ? ProfileHelper.getFullName(agency, LocaleHelper.getLocale('ru'), false) : 'Не указано'
}

def salesPointCity = { it ->

    def salesPoint = EntityStorage.get().resolve(it.salesPoint)?.entity
    return Environment.getPublished(DictionaryCache.class).resolveReference(ProfileHelper.filterAddresses(salesPoint?.addresses, AddressType.FACTUAL)?.city)
}

def departureCityName = { it ->

    return DictHelper.findCityByCode(it.departureCityCode, CodeSystem.IATA)?.toString(new Locale("ru"))
}

def arriveCityName = { it ->

    return DictHelper.findCityByCode(it.arriveCityCode, CodeSystem.IATA)?.toString(new Locale("ru"))
}

def travellerType = { it ->

    PassengerTypeValue ptv = DictHelper.getPassengerTypeValue(it.travellerType);
    if(ptv == PassengerTypeValue.ADULT || ptv == PassengerTypeValue.SENIOR || ptv == PassengerTypeValue.YOUTH || ptv == PassengerTypeValue.STUDENT) {
        return 'ВЗР'
    }

    if(ptv == PassengerTypeValue.CHILD || ptv == PassengerTypeValue.CHILD_UNACCOMPANIED) {
        return 'РБ'
    }

    if(ptv == PassengerTypeValue.INFANT || ptv == PassengerTypeValue.INFANT_WITH_SITE) {
        return 'РМ'
    }

    if(ptv == PassengerTypeValue.ADULT_COMPANION || ptv == PassengerTypeValue.FAMILY_ACCOMPANIED) {
        return 'Сопровождающий'
    }

    return null
}

def genderType = { it ->

    if(TextUtil.isSame(it.travellerGender, 'Мужской') || TextUtil.isSame(it.travellerGender, 'Male')) {
        return 'МУЖ'
    }

    if(TextUtil.isSame(it.travellerGender, 'Женский') || TextUtil.isSame(it.travellerGender, 'Female')){
        return 'ЖЕН'
    }

    return null
}

// Header
page{"Registry"} {

    // Set portrait mode
    landscape(true)

    // Set narrow margins
    margin(0.25, 0.25, 0.75, 0.75)

    // Set scale
    scale(60)

    // Set preserve mode
    preserve(false)

    def products = [:]

    products['sell'] = []
    products['refund'] = []
    products['exchange'] = []

    // Initialization
    tickets{

        def batch = null

        if(it.operationBatch == OperationBatch.SELL) {
            batch = 'sell'
        } else if(it.operationBatch == OperationBatch.REFUND) {
            batch = 'refund'
        } else if(it.operationBatch == OperationBatch.EXCHANGE) {
            batch = 'exchange'
        }

        if(batch) {
            products[batch].add(it);
        }
    }

    // Report header
    text('Реестр продажи/возврата/обмена воздушных перевозок по специальному тарифу в рамках Договора о предоставлении субсидий', 'titleH1', 18, 1);
    2.times{nextRow()}

    nextColumn()
    text('Перевозчик:', 'titleH2|ahr')
    nextColumn()
    text('ОАО "АК "Трансаэро"', 'titleH2|ahl')
    nextRow()

    nextColumn()
    text('Агентство:', 'titleH2|ahr')
    nextColumn()
    text(agencyName(), 'titleH2|ahl')
    nextRow()

    columnWidth(5)
    nextColumn()
    columnWidth(12)
    nextColumn()
    columnWidth(12)
    nextColumn()
    columnWidth(12)
    nextColumn()
    columnWidth(12)
    nextColumn()
    columnWidth(10)
    nextColumn()
    columnWidth(8)
    nextColumn()
    columnWidth(16)
    nextColumn()
    columnWidth(16)
    nextColumn()
    columnWidth(16)
    nextColumn()
    columnWidth(16)
    nextColumn()
    columnWidth(16)
    nextColumn()
    columnWidth(12)
    nextColumn()
    columnWidth(10)
    nextColumn()
    columnWidth(10)
    nextColumn()
    columnWidth(5)
    nextColumn()
    columnWidth(10)
    nextColumn()
    columnWidth(16)
    nextRow()

    // Table header
    text('№ п/п', 'columnHeader|wrap|ba')
    nextColumn()
    text('Пункт оформления перевозочного документа', 'columnHeader|wrap|ba')
    nextColumn()
    text('Наименование перевозочного документа', 'columnHeader|wrap|ba')
    nextColumn()
    text('Серия, номер перевозочного документа', 'columnHeader|wrap|ba')
    nextColumn()
    text('Дата оформления / возврата перевозочного документа', 'columnHeader|wrap|ba')
    nextColumn()
    text('Дата перевозки по перевозочному документу', 'columnHeader|wrap|ba')
    nextColumn()
    text('Номер рейса', 'columnHeader|wrap|ba')
    nextColumn()
    text('Аэропорт отправления', 'columnHeader|wrap|ba')
    nextColumn()
    text('Аэропорт назначения', 'columnHeader|wrap|ba')
    nextColumn()
    text('Фамилия. имя, отчество пассажира', 'columnHeader|wrap|ba')
    nextColumn()
    text('Паспорт/свидетельство о рождении, документ, подтверждающий факт установления инвалидности', 'columnHeader|wrap|ba')
    nextColumn()
    text('Категория пассажира, ВЗР / РБ / РМ / ВЗР-инвалид / РБ-инвалид /сопровождающий', 'columnHeader|wrap|ba')
    nextColumn()
    text('Вид тарифа', 'columnHeader|wrap|ba')
    nextColumn()
    text('Величина тарифа, руб.', 'columnHeader|wrap|ba')
    nextColumn()
    text('Дата рождения пассажира ', 'columnHeader|wrap|ba')
    nextColumn()
    text('Пол пассажира ', 'columnHeader|wrap|ba')
    nextColumn()
    text('Плата за возврат, руб ', 'columnHeader|wrap|ba')
    nextColumn()
    text('Номер перевозочного документа, принятого к обмену (при обмене) / в дополнение к которому выписан (для сопровождающего) ', 'columnHeader|wrap|ba')
    nextRow()

    def count = 0;

    18.times{

        number(count + 1, 'columnHeader|wrap|ba')
        nextColumn()

        count++;
    }

    nextRow()

    // Sell data
    text('ПРОДАЖА', 'dataText|ahl|bold|ba', 18, 1)
    nextRow()

    count = 0;

    for(product in products['sell']) {

        text(String.valueOf(count + 1), 'dataNumber|ahr|ba')
        nextColumn()
        text(salesPointCity(product)?.toString(), 'dataText|ba')
        nextColumn()
        text('Авиабилет', 'dataText|ba')
        nextColumn()
        text(product.ticketNumber, 'dataText|ba')
        nextColumn()
        date(product.issueDate, 'dataDate|ba')
        nextColumn()
        date(product.departureDate, 'dataDate|ba')
        nextColumn()
        text(TextUtil.join('/', product.flightNumbers, true), 'dataText|ba')
        nextColumn()
        text(departureCityName(product), 'dataText|ba')
        nextColumn()
        text(arriveCityName(product), 'dataText|ba')
        nextColumn()
        text(product.travellerName, 'dataText|ba')
        nextColumn()
        text(product.travellerPassportNumber, 'dataText|ba')
        nextColumn()
        text(travellerType(product), 'dataText|ba')
        nextColumn()
        text(product.fareBasisLine, 'dataText|ba')
        nextColumn()
        number(product.equivalentFare, 'dataNumber|ba')
        nextColumn()
        date(product.travellerBirthday, 'dataDate|ba')
        nextColumn()
        text(genderType(product), 'dataText|ba')
        nextColumn()
        text(null, 'dataText|ba')
        nextColumn()
        text(product.getRelatedTicketNumber(), 'dataText|ba')
        nextRow()

        count++;
    }

    text('ПРОДАЖА ИТОГО:', 'dataText|ahl|bold|ba', 3, 1)
    3.times{nextColumn()}

    10.times{

        text(null, 'dataText|ba')
        nextColumn()
    }

    formula(count > 0 ? "SUM(${cellIndex(-count - 1, 0)}:${cellIndex(-1, 0)})" : null, 'dataNumber|bold|ba')
    nextColumn()
    
    4.times{

        text(null, 'dataText|ba')
        nextColumn()
    }

    2.times{nextRow()}

    // Refund data
    text('ВОЗВРАТ', 'dataText|ahl|bold|ba', 18, 1)
    nextRow()

    count = 0

    for(product in products['refund']) {

        text(String.valueOf(count + 1), 'dataNumber|ahr|ba')
        nextColumn()
        text(salesPointCity(product)?.toString(), 'dataText|ba')
        nextColumn()
        text('Авиабилет', 'dataText|ba')
        nextColumn()
        text(product.ticketNumber, 'dataText|ba')
        nextColumn()
        date(product.issueDate, 'dataDate|ba')
        nextColumn()
        date(product.departureDate, 'dataDate|ba')
        nextColumn()
        text(TextUtil.join('/', product.flightNumbers, true), 'dataText|ba')
        nextColumn()
        text(departureCityName(product), 'dataText|ba')
        nextColumn()
        text(arriveCityName(product), 'dataText|ba')
        nextColumn()
        text(product.travellerName, 'dataText|ba')
        nextColumn()
        text(product.travellerPassportNumber, 'dataText|ba')
        nextColumn()
        text(travellerType(product), 'dataText|ba')
        nextColumn()
        text(product.fareBasisLine, 'dataText|ba')
        nextColumn()
        number(MiscUtil.negate(product.equivalentFare), 'dataNumber|ba')
        nextColumn()
        date(product.travellerBirthday, 'dataDate|ba')
        nextColumn()
        text(genderType(product), 'dataText|ba')
        nextColumn()
        number(product?.penalty, 'dataNumber|ba')
        nextColumn()
        text(product.getRelatedTicketNumber(), 'dataText|ba')
        nextRow()

        count++;
    }

    text('ВОЗВРАТ ИТОГО:', 'dataText|ahl|bold|ba', 3, 1)
    3.times{nextColumn()}

    10.times{

        text(null, 'dataText|ba')
        nextColumn()
    }

    formula(count > 0 ? "SUM(${cellIndex(-count - 1, 0)}:${cellIndex(-1, 0)})" : null, 'dataNumber|bold|ba')
    nextColumn()
    
    2.times{

        text(null, 'dataText|ba')
        nextColumn()
    }

    formula(count > 0 ? "SUM(${cellIndex(-count - 1, 0)}:${cellIndex(-1, 0)})" : null, 'dataNumber|bold|ba')
    nextColumn()

    text(null, 'dataText|ba')

    2.times{nextRow()}

    // Exchange data
    text('ОБМЕН', 'dataText|ahl|bold|ba', 18, 1)
    nextRow()

    count = 0

    for(product in products['exchange']) {

        text(String.valueOf(count + 1), 'dataText|ahr|ba')
        nextColumn()
        text(salesPointCity(product)?.toString(), 'dataText|ba')
        nextColumn()
        text('Авиабилет', 'dataText|ba')
        nextColumn()
        text(product.ticketNumber, 'dataText|ba')
        nextColumn()
        date(product.issueDate, 'dataDate|ba')
        nextColumn()
        date(product.departureDate, 'dataDate|ba')
        nextColumn()
        text(TextUtil.join('/', product.flightNumbers, true), 'dataText|ba')
        nextColumn()
        text(departureCityName(product), 'dataText|ba')
        nextColumn()
        text(arriveCityName(product), 'dataText|ba')
        nextColumn()
        text(product?.getNameInGDS(), 'dataText|ba')
        nextColumn()
        text(product?.travellerPassportNumber, 'dataText|ba')
        nextColumn()
        text(travellerType(product), 'dataText|ba')
        nextColumn()
        text(product.fareBasisLine, 'dataText|ba')
        nextColumn()
        number(product.equivalentFare, 'dataNumber|ba')
        nextColumn()
        date(product.travellerBirthday, 'dataDate|ba')
        nextColumn()
        text(genderType(product), 'dataText|ba')
        nextColumn()
        text(null, 'dataNumber|ba')
        nextColumn()
        text(product.getRelatedTicketNumber(), 'dataText|ba')
        nextRow()

        count++;
    }

    text('ОБМЕН ИТОГО:', 'dataText|ahl|bold|ba', 3, 1)
    3.times{nextColumn()}

    10.times{

        text(null, 'dataText|ba')
        nextColumn()
    }

    formula(count > 0 ? "SUM(${cellIndex(-count - 1, 0)}:${cellIndex(-1, 0)})" : null, 'dataNumber|bold|ba')
    nextColumn()
    
    4.times{

        text(null, 'dataText|ba')
        nextColumn()
    }
}