/**
 * Copyright (C) 2019 Patrik Dufresne Service Logiciel <info@patrikdufresne.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package com.planimod.ui.printing;

import static com.planimod.ui.Localized._;

import java.util.Date;

import org.eclipse.nebula.paperclips.core.EmptyPrint;
import org.eclipse.nebula.paperclips.core.grid.GridPrint;
import org.eclipse.nebula.paperclips.core.page.PageNumber;
import org.eclipse.nebula.paperclips.core.page.PageNumberFormat;
import org.eclipse.nebula.paperclips.core.page.PageNumberPrint;
import org.eclipse.nebula.paperclips.core.Print;
import org.eclipse.nebula.paperclips.core.text.TextPrint;

import org.eclipse.swt.SWT;

import com.patrikdufresne.printing.FontDataUtil;
import com.patrikdufresne.printing.IPrintFactory;
import com.patrikdufresne.printing.MultipleHeaderSingleFooterPrintFactory;
import com.patrikdufresne.util.DateFormatRegistry;

/**
 * Default implementation if {@link IPrintFactory} for Planimod application. This factory provide default header and
 * footer based on the title.
 * <p>
 * Sub-classes must implement the abstract function {@link #createBodyArea()} to create the content of this print
 * factory. Default header will be created if the title or the subtitle is sets. Default footer is added with printing
 * date and page count.
 * 
 * @author Patrik Dufresne
 * 
 */
public abstract class PlanimodPrintFactory extends MultipleHeaderSingleFooterPrintFactory {

    /**
     * Instance of this class represent a printing section with a different header. This implementation create header
     * using the title and subtitle value.
     * 
     * @author Patrik Dufresne
     * 
     */
    public abstract class PlanimodSection implements HeaderSection {

        private String subTitle;

        private String title;

        /**
         * Create a new printing section with title and subtitle specified.
         * 
         * @param title
         * @param subTitle
         */
        public PlanimodSection(String title, String subTitle) {
            this.title = title;
            this.subTitle = subTitle;
        }

        /**
         * This implementation create header using the title and subtitle value if not null.
         */
        @Override
        public Print createHeaderArea(PageNumber pageNumber) {
            if (this.title == null && this.subTitle == null) {
                return null;
            }
            GridPrint grid = new GridPrint("c:d:g");
            if (this.title != null) {
                grid.add(new TextPrint(this.title, FontDataUtil.HEADER1, SWT.CENTER));
            }
            if (this.subTitle != null) {
                grid.add(new TextPrint(this.subTitle, FontDataUtil.HEADER2, SWT.CENTER));
            }
            return grid;
        }

    }

    /*
     * The printing date.
     */
    private Date printTime;

    /**
     * Sub title
     */
    private String subTitle;

    /**
     * title
     */
    private String title;

    /**
     * Create a new print factory. Subclasses should set default title and sub title.
     * 
     * @param jobName
     *            the job name
     */
    public PlanimodPrintFactory(String jobName) {
        super(jobName);
    }

    /**
     * Sub-classes should implement this function.
     * 
     * @return the print body.
     */
    protected Print createBodyArea() {
        return new TextPrint("TODO", FontDataUtil.DEFAULT);
    }

    /**
     * This implementation create a footer with the page count and the date.
     */
    @Override
    protected Print createFooterArea(PageNumber pageNumber) {

        GridPrint grid = new GridPrint("left:default:grow(1), center:default:grow(1), right:default:grow(1)");

        // Left
        grid.add(createLeftFooterPrint(pageNumber));

        // Middle
        grid.add(createMiddleFooterPrint(pageNumber));

        // Right
        grid.add(createRightFooterPrint(pageNumber));

        return grid;
    }

    /**
     * This function is called to create the text value for the left sided footer. This implementation return a label
     * 'print in date'.
     * 
     * @param pageNumber
     *            The page number
     * @return the text value
     * @see #createBodyArea()
     * 
     */
    protected Print createLeftFooterPrint(PageNumber pageNumber) {
        String text = _("Imprimer le %s par Planimod", DateFormatRegistry.format(getPrintTime(), DateFormatRegistry.DATETIME | DateFormatRegistry.ISO));
        return new TextPrint(text, FontDataUtil.SMALL);
    }

    protected Print createMiddleFooterPrint(PageNumber pageNumber) {
        return new EmptyPrint();
    }

    /**
     * This function is called to create the text value for the right sided footer. This implementation return the page
     * count.
     * 
     * @param pageNumber
     * @return
     */
    protected Print createRightFooterPrint(PageNumber pageNumber) {
        PageNumberPrint pageNumberPrint = new PageNumberPrint(pageNumber, FontDataUtil.SMALL, SWT.RIGHT);
        pageNumberPrint.setPageNumberFormat(new PageNumberFormat() {
            @Override
            public String format(PageNumber pn) {
                return _("%d de %d", Integer.valueOf(pn.getPageNumber() + 1), Integer.valueOf(pn.getPageCount()));
            }
        });
        return pageNumberPrint;
    }

    /**
     * This implementation is creating a single section using the function #createBodyPrint to create the body of the
     * section.
     */
    @Override
    protected void createSections() {
        addSection(new PlanimodSection(getTitle(), getSubTitle()) {
            @Override
            public Print createBodyArea() {
                return PlanimodPrintFactory.this.createBodyArea();
            }
        });
    }

    /**
     * Return the print time of this print.
     * 
     * @return
     */
    protected Date getPrintTime() {
        if (this.printTime == null) {
            this.printTime = new Date();
        }
        return this.printTime;
    }

    /**
     * Return the sub-title.
     * 
     * @return
     */
    public String getSubTitle() {
        return this.subTitle;
    }

    /**
     * Return the title.
     * 
     * @return
     */
    public String getTitle() {
        return this.title;
    }

    /**
     * Sets the sub title of this print factory.
     * 
     * @param subTitle
     */
    public void setSubTitle(String subTitle) {
        this.subTitle = subTitle;
    }

    /**
     * Sets the title of this print factory.
     * 
     * @param title
     */
    public void setTitle(String title) {
        this.title = title;
    }

}
