/*
 * このソースコードは blanco Frameworkにより自動生成されました。
 */
package blanco.sample.pdf.report;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List;

import blanco.commons.util.BlancoStringUtil;
import blanco.pdf.page.BlancoPdfPageUtil;
import blanco.pdf.page.BlancoPdfPageWriter;
import blanco.pdf.page.valueobject.BlancoPdfPageDef;
import blanco.pdf.valueobject.BlancoPdfMetrix;
import blanco.pdf.valueobject.BlancoPdfSetting;
import blanco.sample.pdf.report.items.Yoko01PdfReportBlock01Items;
import blanco.sample.pdf.report.items.Yoko01PdfReportItems;

import com.lowagie.text.pdf.PdfWriter;

/**
 * PDF レポート。
 */
public class Yoko01PdfReport {
    /**
     * ページ定義オブジェクト。
     */
    private BlancoPdfPageDef fPageDef;

    /**
     * ページ・ライター・オブジェクト。
     */
    private BlancoPdfPageWriter fPageWriter;

    /**
     * 1 ページ分のデータをセットします。
     *
     * @param pdfSetting PDF 項目群。
     * @param outStream 出力ストリーム。
     */
    public Yoko01PdfReport(final BlancoPdfSetting pdfSetting, final OutputStream outStream) {
        fPageDef = BlancoPdfPageUtil.read(pdfSetting, "yoko01");
        fPageWriter = new BlancoPdfPageWriter(pdfSetting.getConfPath(), fPageDef, outStream);
    }

    /**
     * 1 ページ分のデータを PDF に書き出します。
     *
     * @param pdfItems PDF 項目群。
     */
    public void writeItems(final Yoko01PdfReportItems pdfItems) {
        for (int occur = 0; occur < pdfItems.getBlock01List().size(); occur++) {
            final Yoko01PdfReportBlock01Items blockItems = pdfItems.getBlock01List().get(occur);
            {
                final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
                metrix.setFont("gothic");
                metrix.setFontSize(20);
                if (blockItems.getAaa() != null) {
                    fPageWriter.drawText(140.0f + 0.0f * occur, 180.0f + 60.0f * occur, blockItems.getAaa(), metrix);
                }
            }
            {
                final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
                metrix.setFont("gothic");
                metrix.setFontSize(25);
                if (blockItems.getBbb() != null) {
                    fPageWriter.drawText(300.0f + 0.0f * occur, 180.0f + 60.0f * occur, blockItems.getBbb(), metrix);
                }
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("gothic");
            metrix.setFontSize(12);
            final DecimalFormat format = new DecimalFormat();
            if (pdfItems.getPageNo() != null) {
                fPageWriter.drawText(740.0f, 30.0f, BlancoStringUtil.padLeft(format.format(pdfItems.getPageNo()), 3, ' '), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("gothic");
            metrix.setFontSize(12);
            final DecimalFormat format = new DecimalFormat();
            if (pdfItems.getTotalPageCount() != null) {
                fPageWriter.drawText(770.0f, 30.0f, format.format(pdfItems.getTotalPageCount()), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(12);
            if (pdfItems.getField00() != null) {
                fPageWriter.drawText(144.0f, 144.0f, pdfItems.getField00(), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(12);
            if (pdfItems.getField01() != null) {
                fPageWriter.drawText(72.0f, 72.0f, BlancoStringUtil.padLeft(pdfItems.getField01(), 10, ' '), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(24);
            final DecimalFormat format = new DecimalFormat("###,###.###");
            format.setMinimumFractionDigits(3);
            if (pdfItems.getField02() != null) {
                fPageWriter.drawText(144.0f, 72.0f, BlancoStringUtil.padLeft(format.format(pdfItems.getField02()), 10, ' '), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(24);
            final DecimalFormat format = new DecimalFormat("###,###.###");
            if (pdfItems.getField03() != null) {
                fPageWriter.drawText(144.0f, 72.0f, BlancoStringUtil.padLeft(format.format(pdfItems.getField03()), 10, ' '), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(24);
            if (pdfItems.getField04() != null) {
                fPageWriter.drawTextCenter(220.0f, 100.0f, pdfItems.getField04(), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(12);
            if (pdfItems.getNextpage01() != null) {
                fPageWriter.drawText(250.0f, 510.0f, pdfItems.getNextpage01(), metrix);
            }
        }
        {
            final BlancoPdfMetrix metrix = new BlancoPdfMetrix();
            metrix.setFont("mincho");
            metrix.setFontSize(12);
            if (pdfItems.getNextpage02() != null) {
                fPageWriter.drawText(350.0f, 510.0f, pdfItems.getNextpage02(), metrix);
            }
        }
    }

    /**
     * ページをすべて出力します。
     *
     * @param itemsList 出力したい項目群。
     */
    public void writeItemsList(final List<Yoko01PdfReportItems> itemsList) {
        boolean isFirst = true;
        for (Yoko01PdfReportItems items : itemsList) {
            if (isFirst) {
                isFirst = false;
            } else {
                nextPage();
            }
            writeItems(items);
        }
    }

    /**
     * 改ページします。
     */
    public void nextPage() {
        fPageWriter.nextPage();
    }

    /**
     * 正規化の実施。ページブレークなどの処理をおこないます。
     *
     * @param itemsList 正規化したい項目群。
     */
    public void normalize(final List<Yoko01PdfReportItems> itemsList) {
        consolidatePage(itemsList);
        breakPageByRowCount(itemsList);
        processPageContinuity(itemsList);
        omitDitto(itemsList);

        // ページ関連情報の埋め込み。
        applyPageNo(itemsList);
    }

    /**
     * ページの集約処理をおこないます。すべての項目の値をもとに処理されるものです。
     *
     * @param itemsList ページ集約したい項目群。
     */
    public void consolidatePage(final List<Yoko01PdfReportItems> itemsList) {
        Yoko01PdfReportItems prev = null;
        for (int index = 0; index < itemsList.size(); index++) {
            final Yoko01PdfReportItems next = itemsList.get(index);
            if (prev == null) {
                prev = next;
                continue;
            }

            // 項目の値を比較。
            if (canConsolidatePage(prev, next)) {
                // ページを集約します。
                prev.getBlock01List().addAll(next.getBlock01List());
                itemsList.remove(index);
                index--;
            } else {
                prev = next;
            }
        }
    }

    /**
     * ページ集約できるかどうかをチェック。
     *
     * @param prev 比較元。
     * @param next 比較先。
     * @return 集約できるかどうか。
     */
    public boolean canConsolidatePage(final Yoko01PdfReportItems prev, final Yoko01PdfReportItems next) {
        if (prev.getPageNo() == null || next.getPageNo() == null) {
            if (prev.getPageNo() != next.getPageNo()) {
                return false;
            }
        } else if (prev.getPageNo().compareTo(next.getPageNo()) != 0) {
            return false;
        }

        if (prev.getTotalPageCount() == null || next.getTotalPageCount() == null) {
            if (prev.getTotalPageCount() != next.getTotalPageCount()) {
                return false;
            }
        } else if (prev.getTotalPageCount().compareTo(next.getTotalPageCount()) != 0) {
            return false;
        }

        if (prev.getField00() == null || next.getField00() == null) {
            if (prev.getField00() != next.getField00()) {
                return false;
            }
        } else if (prev.getField00().compareTo(next.getField00()) != 0) {
            return false;
        }

        if (prev.getField01() == null || next.getField01() == null) {
            if (prev.getField01() != next.getField01()) {
                return false;
            }
        } else if (prev.getField01().compareTo(next.getField01()) != 0) {
            return false;
        }

        if (prev.getField02() == null || next.getField02() == null) {
            if (prev.getField02() != next.getField02()) {
                return false;
            }
        } else if (prev.getField02().compareTo(next.getField02()) != 0) {
            return false;
        }

        if (prev.getField03() == null || next.getField03() == null) {
            if (prev.getField03() != next.getField03()) {
                return false;
            }
        } else if (prev.getField03().compareTo(next.getField03()) != 0) {
            return false;
        }

        if (prev.getField04() == null || next.getField04() == null) {
            if (prev.getField04() != next.getField04()) {
                return false;
            }
        } else if (prev.getField04().compareTo(next.getField04()) != 0) {
            return false;
        }

        if (prev.getNextpage01() == null || next.getNextpage01() == null) {
            if (prev.getNextpage01() != next.getNextpage01()) {
                return false;
            }
        } else if (prev.getNextpage01().compareTo(next.getNextpage01()) != 0) {
            return false;
        }

        if (prev.getNextpage02() == null || next.getNextpage02() == null) {
            if (prev.getNextpage02() != next.getNextpage02()) {
                return false;
            }
        } else if (prev.getNextpage02().compareTo(next.getNextpage02()) != 0) {
            return false;
        }

        return true;
    }

    /**
     * 所定の行数をもとにページをブレークします。こちらではページを分割します。
     *
     * @param itemsList ブレーク処理したい項目群。
     */
    public void breakPageByRowCount(final List<Yoko01PdfReportItems> itemsList) {
        for (int index = 0; index < itemsList.size(); index++) {
            final Yoko01PdfReportItems look = itemsList.get(index);
            if (look.getBlock01List().size() > 5) {
                // ページを分割します。
                final Yoko01PdfReportItems add = new Yoko01PdfReportItems();
                add.setPageNo(look.getPageNo());
                add.setTotalPageCount(look.getTotalPageCount());
                add.setField00(look.getField00());
                add.setField01(look.getField01());
                add.setField02(look.getField02());
                add.setField03(look.getField03());
                add.setField04(look.getField04());
                add.setNextpage01(look.getNextpage01());
                add.setNextpage02(look.getNextpage02());
                add.setHidden01(look.getHidden01());

                for (int indexBlock = 0; indexBlock < 5; indexBlock++) {
                    add.getBlock01List().add(look.getBlock01List().get(0));
                    look.getBlock01List().remove(0);
                }
                itemsList.add(index, add);
            }
        }
    }

    /**
     * ページの継続性に関する処理を実施します。
     *
     * @param itemsList 処理対象。
     */
    public void processPageContinuity(final List<Yoko01PdfReportItems> itemsList) {
        Yoko01PdfReportItems prev = null;
        for (int index = 0; index < itemsList.size(); index++) {
            final Yoko01PdfReportItems next = itemsList.get(index);
            if (prev == null) {
                prev = next;
                continue;
            }

            // 項目の値を比較。
            if (canConsolidatePage(prev, next)) {
                prev.setNextpage02(null);
            } else {
                prev.setNextpage01(null);
            }
            prev = next;
        }
        prev.setNextpage01(null);
    }

    /**
     * ページ番号を付与。
     *
     * @param itemsList ページ処理したい項目群。
     */
    public void applyPageNo(final List<Yoko01PdfReportItems> itemsList) {
        int pageNo = 1;
        for (Yoko01PdfReportItems items : itemsList) {
            items.setPageNo(BigDecimal.valueOf(pageNo++));
        }
        for (Yoko01PdfReportItems items : itemsList) {
            items.setTotalPageCount(BigDecimal.valueOf(itemsList.size()));
        }
    }

    /**
     * 同上項目の省略を実施。
     *
     * @param itemsList 省略処理をしたい項目群。
     */
    public void omitDitto(final List<Yoko01PdfReportItems> itemsList) {
    }

    /**
     * グリッド・シートを描画します。
     */
    public void drawGridSheet() {
        fPageWriter.drawGridSheet();
    }

    /**
     * クローズします。
     */
    public void close() {
        fPageWriter.close();
    }

    /**
     * PDF ライターを取得します。
     *
     * @return 内部的に利用しているライター。
     */
    @Deprecated
    public PdfWriter getPdfWriter() {
        return fPageWriter.getWriter();
    }
}
