import java.text.SimpleDateFormat
import java.util.Map
import java.util.TreeMap
import java.util.Map.Entry
import java.util.Iterator
import com.gridnine.xtrip.common.model.stockcontrol.StockBlankIndex
import com.gridnine.xtrip.common.reports.StockBlankReportHelper
import com.gridnine.xtrip.common.reports.StockBlankReportHelper.StockBlankBatch
import com.gridnine.xtrip.common.reports.StockBlankReportHelper.StockBlankReportBatch
import com.gridnine.xtrip.common.model.booking.BlankType
import com.gridnine.xtrip.common.model.dict.ProductCategory
import com.gridnine.xtrip.common.model.entity.EntityStorage
import com.gridnine.xtrip.common.model.profile.SalesPoint
import com.gridnine.xtrip.common.model.profile.CashRegisterWorkplace
import com.gridnine.xtrip.common.model.helpers.ProfileHelper
import com.gridnine.xtrip.common.l10n.model.LocaleHelper
import com.gridnine.xtrip.common.model.dict.ManagerType
import com.gridnine.xtrip.common.model.profile.Organization
import com.gridnine.xtrip.common.model.profile.Person
import com.gridnine.xtrip.common.model.EntityReference
import com.gridnine.xtrip.common.model.EntityContainer
import com.gridnine.xtrip.common.model.profile.OrganizationType
//CREATING STYLES
createStyle(name: 'title',fontBold: true, h_span: 2, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'titleWide',fontBold: true, h_span: 9, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'metadataTitle',fontBold: true, h_span: 5, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'metadataValue', parent: 'metadataTitle', h_span: 3, fontBold: true, h_alignment: 'CENTER',fontHeight:10)
createStyle(name: 'metadataDateValue', parent: 'metadataValue', h_span: 2,  v_alignment: 'CENTER')
createStyle(name: 'header',fontBold: true, h_span: 2, v_span: 2, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'header2',fontBold: true, h_span: 3, v_span: 2, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'data',fontBold: false,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:7, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN')
createStyle(name: 'wideData',fontBold: false,  h_alignment: 'LEFT', v_alignment: 'CENTER', fontHeight:7, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN',h_span:3)
createStyle(name: 'textData',parent: 'data')
createStyle(name: 'numberData',parent: 'data',h_alignment: 'RIGHT')
createStyle(name: 'dateData',parent: 'data',h_alignment: 'RIGHT',format: 'm/d/yy')
createStyle(name: 'statusGroupTitle', parent: 'header', h_span: 2, h_alignment: 'CENTER', fontBold: true)
createStyle(name: 'statusGroupNumber',parent: 'statusGroupTitle',  h_span: 1)
createStyle(name: 'subagencyGroupTitle', parent: 'statusGroupTitle')
createStyle(name: 'subagencyGroupNumber',parent: 'subagencyGroupTitle',  h_span: 1)
createStyle(name: 'totalTitle', parent: 'subagencyGroupTitle')
createStyle(name: 'totalNumber',parent: 'totalTitle', h_span: 1)
createStyle(name: 'GroupNumber',parent: 'header', v_span: 2)
createStyle(name: 'titleH1', fontBold: true, h_span: 1, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'headerH1',fontBold: true, h_span: 3,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'headerH2',fontBold: true, v_span: 2, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'headerH3',fontBold: true, h_span: 2,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'dataBold',fontBold: true,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:7, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN')
createStyle(name: 'wideDataNoBorders',fontBold: false,  h_alignment: 'LEFT', v_alignment: 'CENTER', fontHeight:7,h_span:3)
// Properties
def periodBeginParameter = parameters['periodBeginP']//?.requestedParameters.periodBeginP;
def periodEndParameter = parameters['periodEndP']//?.periodEndP;
def locationParameter = parameters['location']//?.location;
def groupingParameter = !parameters['groupBlankEnabled']//?.location;
def blankOwnerParameter = parameters['owner']//?.requestedParameters.periodBeginP;


def agencyCtr ={
    def locationEntity = EntityStorage.get().resolve(locationParameter)?.entity
    if (locationEntity instanceof CashRegisterWorkplace){
        def salesPoint = EntityStorage.get().resolve(locationEntity.getSalesPoint())?.getEntity()
        def agencyCtr = EntityStorage.get().resolve(salesPoint?.agency)
        return agencyCtr
    }
    if (locationEntity instanceof SalesPoint){
        def agencyCtr = EntityStorage.get().resolve(locationEntity?.agency)
        return agencyCtr
    }
    if (locationEntity instanceof Organization){
        return EntityStorage.get().resolve(locationParameter)
    }
    if(locationEntity instanceof Person){
        return ProfileHelper.getMainEmployment(locationEntity)
    }
}

def agencyName = {
    tmp=agencyCtr()?.getEntity()
    return tmp ? ProfileHelper.getFullName(tmp, LocaleHelper.getLocale('ru', 'RU'), false) : 'Не указано'
}

def salesPointName = {
    def salesPoint = EntityStorage.get().resolve(locationParameter)?.entity
    if (salesPoint instanceof SalesPoint){
        return salesPoint ? ProfileHelper.getFullName(salesPoint) : 'Не указано'
    }else if (salesPoint instanceof Organization){
        return agencyName()
    }else if(salesPoint instanceof Person){
        return ProfileHelper.getFullName(salesPoint,new Locale("ru"),false)
    } else{
        return salesPoint ? salesPoint.getName() : ""
    }
}
def blankOwnerName = {
    def agency = EntityStorage.get().resolve(blankOwnerParameter)?.entity
    return agency ? ProfileHelper.getFullName(agency, LocaleHelper.getLocale('ru', 'RU'), false) : 'Не указано'
}

def format = new SimpleDateFormat('dd.MM.yy HH:mm')
//REPORT
page{'Отчет'}{
    //title
    rowHeight(20)
    5.times{nextColumn()}
    text('Отчет', 'title')
    nextRow()
    nextColumn();nextColumn();text('О движении бланков строгой отчетности ', 'metadataTitle')
    nextRow()
    setStyle('titleH1')
    2.times {nextColumn()}
    text(blankOwnerName()+' '+salesPointName(), 'titleWide')
    nextRow()
    setStyle('titleH1')
    nextColumn();text('По состоянию на период с', 'metadataValue')
    nextColumn();text(periodBeginParameter != null ? format.format(periodBeginParameter) : '?', 'metadataDateValue')
    nextColumn();text('по', 'titleH1')
    nextColumn();text(periodEndParameter != null ? format.format(periodEndParameter) : '?', 'metadataDateValue')
    nextRow()
    nextColumn()
    text(agencyName(), 'titleWide')
    //header
    rowHeight(15)
    nextRow()
    text('Бланк', 'header2')
    rowHeight(30)
    nextColumn();text('Остаток на '+ (periodBeginParameter != null ? format.format(periodBeginParameter) : '?'), 'headerH3')
    nextColumn();text('Кол-во', 'headerH2')
    nextColumn();text('Приход', 'headerH3')
    nextColumn();text('Кол-во', 'headerH2')
    nextColumn();text('Расход', 'headerH3')
    nextColumn();text('Кол-во', 'headerH2')
    nextColumn();text('Остаток на '+ (periodEndParameter != null ? format.format(periodEndParameter) : '?'), 'headerH3')
    nextColumn();text('Кол-во', 'headerH2')
    nextRow()
    rowHeight(15)
    setStyle('data')
    nextColumn();nextColumn();nextColumn()
    text('Номера бланков', 'headerH3')
    setStyle('data')
    nextColumn();nextColumn();nextColumn();text('Номера бланков', 'headerH3')
    setStyle('data')
    nextColumn();nextColumn();nextColumn();text('Номера бланков', 'headerH3')
    setStyle('data')
    nextColumn();nextColumn();nextColumn();text('Номера бланков', 'headerH3')
    //
    Map<BlankType, StockBlankBatch> map = StockBlankReportHelper.generateData(allTickets,periodBeginParameter,periodEndParameter)

    nextRow()
    // Data
    int totalRowCount=0
    int rowCount=0
    List<Integer> skipRows=new LinkedList<Integer>()

    for(Entry<BlankType, TreeMap<String,StockBlankBatch>>  entry:map.entrySet()){
        setStyle('data')
        text(entry.getKey().getName())
        nextColumn()
        text(entry.getKey().getProductCategory().equals(ProductCategory.AIR)?"ПД":"КРС")
        nextColumn()
        boolean firstEntry=true
        for(Entry<String,StockBlankBatch> entry2 : entry.getValue().entrySet()){
            if(!firstEntry){
                2.times{text("");nextColumn()}
            }else{
                firstEntry=false
            }
            text(entry2.getKey())
            nextColumn()
            StockBlankBatch batch=entry2.getValue()
            //Batches
            Iterator<StockBlankReportBatch> beforeIter = batch.before.iterator()
            Iterator<StockBlankReportBatch> receiptsIter = batch.receipts.iterator()
            Iterator<StockBlankReportBatch> withdrawalsIter =
                    batch.withdrawals.iterator()
            Iterator<StockBlankReportBatch> afterIter = batch.after.iterator()

            StockBlankReportBatch beforeBatch =
                    beforeIter.hasNext() ? beforeIter.next() : null
            StockBlankReportBatch receiptsBatch =
                    receiptsIter.hasNext() ? receiptsIter.next() : null
            StockBlankReportBatch withdrawalsBatch =
                    withdrawalsIter.hasNext() ? withdrawalsIter.next() : null
            StockBlankReportBatch afterBatch =
                    afterIter.hasNext() ? afterIter.next() : null
            boolean first = true
            boolean lastBefore=false
            while ((beforeBatch != null) || (receiptsBatch != null)) {
                if(!first){
                    3.times {text("");nextColumn() }
                }
                StockBlankReportBatch current = receiptsBatch
                if ((receiptsBatch == null)
                || receiptsBatch.isAfter(beforeBatch)||(receiptsBatch.hasBeenPrinted())) {//what if null?
                    current = beforeBatch
                    text(beforeBatch.getBeginString())
                    nextColumn()
                    text(beforeBatch.getEndString())
                    nextColumn()
                    number(beforeBatch.getQuantity())
                    nextColumn()
                    beforeBatch.setPrinted()
                    //shift right
                    3.times {text("");nextColumn()}
                }else if(receiptsBatch != null){//else print receipt here
                    3.times {text("");nextColumn()}
                    text(receiptsBatch.getBeginString())
                    nextColumn()
                    text(receiptsBatch.getEndString())
                    nextColumn()
                    number(receiptsBatch.getQuantity())
                    nextColumn()
                    receiptsBatch.setPrinted()
                }
                boolean newLine=false
                while (((withdrawalsBatch != null) || (afterBatch != null))
                && (current.containsBatch(withdrawalsBatch) || current
                .containsBatch(afterBatch))) {
                    if(newLine){
                        9.times{text("");nextColumn()}
                    }
                    newLine=true
                    boolean printed = false
                    if (current.containsBatch(withdrawalsBatch)) {
                        //Print here withdrawal
                        printed = true
                        text(withdrawalsBatch.getBeginString())
                        nextColumn()
                        text(withdrawalsBatch.getEndString())
                        nextColumn()
                        number(withdrawalsBatch.getQuantity())
                        nextColumn()
                        if (withdrawalsIter.hasNext()) {
                            withdrawalsBatch = withdrawalsIter.next()
                        } else {
                            withdrawalsBatch = null
                        }
                    }
                    if (current.containsBatch(afterBatch)) {
                        if (!printed) {
                            3.times{text("");nextColumn()}
                        }
                        // print here after.
                        text(afterBatch.getBeginString())
                        nextColumn()
                        text(afterBatch.getEndString())
                        nextColumn()
                        number(afterBatch.getQuantity())
                        nextColumn()
                        if (afterIter.hasNext()) {
                            afterBatch = afterIter.next()
                        } else {
                            afterBatch = null
                        }
                    }else{
                        3.times{text("");nextColumn()}
                    }

                    //next row
                    nextRow()
                    rowCount++
                    totalRowCount++
                    first = false
                }
                if (beforeIter.hasNext()&&(beforeBatch.hasBeenPrinted())
                &&(((receiptsBatch != null)
                && (!receiptsBatch.isAfter(beforeBatch)))
                || (receiptsBatch == null))) {
                    beforeBatch = beforeIter.next()
                } else if (receiptsIter.hasNext()) {
                    receiptsBatch = receiptsIter.next()
                }else {
                    if (!(beforeIter.hasNext()) && !(receiptsIter.hasNext())) {
                        break
                    }
                }
            }
        }
        text("Итого по типу бланка:",'wideData')
        setStyle('dataBold')
        2.times {nextColumn();text("")}
        4.times {
            3.times {nextColumn();text("")}
            upperCell= cellIndex(-rowCount, 0)
            formula("SUM(${cellIndex(-1,0)}:${upperCell})")
        }
        totalRowCount++
        skipRows.add(totalRowCount)
        nextRow()
        rowCount=0
    }
    totalRowCount++
    text("Итого:",'wideData')
    setStyle('dataBold')
    2.times {nextColumn();text("")}
    4.times {
        3.times {nextColumn();text("")}
        String formulaString=""
        for(Integer i:skipRows){
            formulaString=formulaString+"+"+cellIndex(-(totalRowCount-i), 0)
        }
        upperCell= cellIndex(-totalRowCount, 0)
        formula(formulaString)
    }



    def directorAgency          = ''
    def mainAccountantAgency    = ''
    Organization orgAgency  = agencyCtr()?.getEntity()

    if(orgAgency != null){
        EntityReference<Person> erP = ProfileHelper.getManager(new EntityReference<Organization>(agencyCtr()), ManagerType.CHIEF_ACCOUNTANT, new Date())
        if(erP != null){
            EntityContainer<Person> ecP = EntityStorage.get().resolve(erP)
            mainAccountantAgency = ProfileHelper.getFullName(ecP.entity,LocaleHelper.getCurrentLocale(), false)
        }
        erP = ProfileHelper.getManager(new EntityReference<Organization>(agencyCtr()), ManagerType.DIRECTOR, new Date())
        if(erP != null){
            EntityContainer<Person> ecP = EntityStorage.get().resolve(erP)
            directorAgency = ProfileHelper.getFullName(ecP.entity,LocaleHelper.getCurrentLocale(), false)
        }
    }

    nextRow()
    nextRow();text('Директор','wideDataNoBorders')
    nextColumn();text(directorAgency,'wideDataNoBorders')
    nextRow();text('Главный бухгалтер','wideDataNoBorders')
    nextColumn();text(mainAccountantAgency,'wideDataNoBorders')
    nextRow();text('Исполнитель', 'wideDataNoBorders')
    nextRow();text('Телефон', 'wideDataNoBorders')
}