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.model.StockBlankReportBatch;
import com.gridnine.xtrip.common.reports.model.StockBlankReportBatchGroup;
import com.gridnine.xtrip.common.model.booking.BlankType;
import com.gridnine.xtrip.common.model.dict.DictionaryCache;
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: 12, 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: 1, 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:2)
createStyle(name: 'dataH2',fontBold: false,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:7, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', v_span:2)
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: 1, v_span:2,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'headerH1_1',fontBold: true, h_span: 1, v_span:1,  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['key-report-params'].periodBegin//?.requestedParameters.periodBeginP;
def periodEndParameter = parameters['key-report-params'].periodEnd//?.periodEndP;
def locationParameter = parameters['key-report-params'].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.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{'Отчет'}{   
    rowHeight(15)
    text('Отчет о движении бланков строгой отчетности '+agencyName()+' c '+format.format(periodBeginParameter)+' по '+format.format(periodEndParameter), 'titleWide')
    nextRow()
    text('Наименование бланков', 'header')
    rowHeight(30)
    nextColumn();text('Наличие на начало периода', 'header')
    nextColumn();text('Получено', 'header')
    nextColumn();text('Реализовано и аннулировано', 'header')
    nextColumn();text('Сдано', 'header')
    nextColumn();text('Остаток на конец периода', 'header')
    nextRow();text('')
    5.times {
    nextColumn();text('Серия и № (от-до)', 'headerH1_1');columnWidth(15);
    nextColumn();text('кол-во', 'headerH1_1');columnWidth(5);
    }
    // Data
    nextRow();
    rowHeight(15)
    setStyle('data')
    int totalRowCount=0;
    int rowCount=0;
    List<Integer> skipRows=new LinkedList<Integer>();

    for(StockBlankReportBatchGroup group:allTickets){
        setStyle('wideData')
        BlankType type = DictionaryCache.get().resolveReference(group.getBlankType());
        text(type.getName());setStyle('data')
        nextColumn();text("",'data');
        boolean first = true;
        //for(Entry<String,StockBlankBatch> entry2 : entry.getValue().entrySet()){
        
            setStyle('data')
            String prefix = group.getPrefix();
            //Batches
            Iterator<StockBlankReportBatch> beforeIter = group.before.iterator();
            Iterator<StockBlankReportBatch> receiptsIter = group.receipt.iterator();
            Iterator<StockBlankReportBatch> withdrawalsIter =
                    group.spend.iterator();
            Iterator<StockBlankReportBatch> afterIter = group.after.iterator();
            Iterator<StockBlankReportBatch> moveIter = group.move.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;
            StockBlankReportBatch moveBatch =
                    moveIter.hasNext() ? moveIter.next() : null;
            while ((beforeBatch != null) || (receiptsBatch != null)) {
                String[] line = new String[15];
                StockBlankReportBatch current = receiptsBatch;
                if ((receiptsBatch == null)
                || receiptsBatch.isAfter(beforeBatch)||
                (receiptsBatch.isPrinted())||
                    (beforeBatch!=null&&(beforeBatch.getBegin()-receiptsBatch.getEnd()==1
                        ||receiptsBatch.getBegin()-beforeBatch.getEnd()==1))) {//what if null?
                    current = beforeBatch;
                    line[0]=prefix+beforeBatch.getBeginString();
                    line[1]=prefix+beforeBatch.getEndString();
                    line[2]=beforeBatch.getQuantity();
                    beforeBatch.setPrinted(true);
                }
                if((receiptsBatch != null)&&((beforeBatch==null)
                    ||beforeBatch.getBegin()-receiptsBatch.getEnd()==1
                    ||receiptsBatch.getBegin()-beforeBatch.getEnd()==1)){//else print receipt here
                    line[3] = prefix+receiptsBatch.getBeginString()
                    line[4] = prefix+receiptsBatch.getEndString()
                    line[5] = receiptsBatch.getQuantity()
                    receiptsBatch.setPrinted(true);
                }
                boolean newLine=false;
                while (((withdrawalsBatch != null) || (afterBatch != null))
                && (current.containsBatch(withdrawalsBatch) || current
                .containsBatch(afterBatch))) {
                    if(newLine){
                        line = new String[15];}
                    newLine=true;
                    boolean printed = false;
                    if (current.containsBatch(withdrawalsBatch)) {
                        //Print here withdrawal
                        printed = true;
                        line[6] = prefix+withdrawalsBatch.getBeginString();
                        line[7] = prefix+withdrawalsBatch.getEndString();
                        line[8] = withdrawalsBatch.getQuantity();
                        if (withdrawalsIter.hasNext()) {
                            withdrawalsBatch = withdrawalsIter.next();
                        } else {
                            withdrawalsBatch = null;
                        }
                    }
                    if (current.containsBatch(moveBatch)) {
                        //Print here withdrawal
                        line[9] = prefix+moveBatch.getBeginString();
                        line[10] = prefix+moveBatch.getEndString();
                        line[11] = moveBatch.getQuantity();
                        if (moveIter.hasNext()) {
                            moveBatch = moveIter.next();
                        } else {
                            moveBatch = null;
                        }
                    }
                    if (current.containsBatch(afterBatch)) {
                        line[12] = prefix+afterBatch.getBeginString();
                        line[13] = prefix+afterBatch.getEndString();
                        line[14] = afterBatch.getQuantity();
                        // print here after.
                        if (afterIter.hasNext()) {
                            afterBatch = afterIter.next();
                        } else {
                            afterBatch = null;
                        }
                    }else{
                    }
                    if(!first){
                       text("",'data');nextColumn();text("",'data');
                    }
                    for(int i=0;i<15;i=i+3){
                    nextColumn();text(line[i],'data');
                    nextColumn();if(line[i+2]!=null)number(Integer.parseInt(line[i+2]),'dataH2'); else text('','dataH2');
                    }
                    //next row
                    nextRow();
                    nextColumn();text("",'data');
                    for(int i=0;i<15;i=i+3){
                    nextColumn();text(line[i+1],'data');nextColumn();
                    }
                    nextRow();
                    rowCount++;
                    rowCount++;
                    totalRowCount++;
                    totalRowCount++;
                    first = false;
                }
                if (beforeIter.hasNext()&&(beforeBatch.isPrinted())
                &&(((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');
        nextColumn();text("",'data');
        5.times {
            nextColumn();text("");
            nextColumn();
            upperCell= cellIndex(-rowCount, 0)
            formula("SUM(${cellIndex(-1,0)}:${upperCell})",'data');
        }
        totalRowCount++;
        skipRows.add(totalRowCount);
        nextRow();
        rowCount=0;
    }
    totalRowCount++;
    text("Итого:",'wideData');
    setStyle('dataBold');
    nextColumn();text("");
    5.times {
        nextColumn();text("");
        nextColumn();
        String formulaString="";
        for(Integer i:skipRows){
            formulaString=formulaString+"+"+cellIndex(-(totalRowCount-i), 0)
        }
        upperCell= cellIndex(-totalRowCount, 0)
        formula(formulaString,'data');
    }
}