/*
 * Copyright 2009 Lari Natri <lari.natri@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU 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 General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package compid.report;

import net.aavalla.utils.jobpool.parameters.FieldInstance;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * This class represents the data of a report. This class is thread safe
 * (including iterators). Use iterator to loop through contained pages.
 * @author Lari Natri
 */
public class ReportModel implements Iterable<ReportPageModel> {

    private static final String DEFAULTTITLE = "unknown";
    private static final String DEFAULTSUBTITLE = "";
    
    private final String title;
    private final String subtitle;
    private final ReporterParams parameters; // can be null
    private final List<ReportPageModel> reportPages; // synchronized in constructor, what?!?

    public ReportModel(String title) {
        this(title,null);
    }
    
    public ReportModel(String title, String subtitle) {
        this(title,subtitle,null);
    }

    public ReportModel(String title, String subtitle, ReporterParams params) {
        this(title,subtitle,params,new ArrayList<ReportPageModel>(1));
    }

    public ReportModel(String title, String subtitle, ReporterParams params, List<ReportPageModel> pages) {
        this.title = (title==null ? DEFAULTTITLE : title);
        this.subtitle = (subtitle==null ? DEFAULTSUBTITLE : subtitle);
        this.parameters = params;
        this.reportPages = Collections.synchronizedList(pages); // for thread safety
    }

    /**
     * Adds a page to this ReportModel if it doesn't exist before.
     * @param page Page to add
     */
    public void addPage(ReportPageModel page) {
        if (!this.reportPages.contains(page)) {
            this.reportPages.add(page);
        }
    }

    /**
     * Returns a page. To ensure thread safety, one should use iterator
     * instead.
     * @param index
     * @return page
     */
    public ReportPageModel getPage(int index) {
        return this.reportPages.get(index);
    }

    /**
     * Removes a page from this ReportModel
     * @param page Page to be removed
     * @return true If page existed and is now removed, false if it didn't
     *         exist in the first place
     */
    public boolean removePage(ReportPageModel page) {
        return this.reportPages.remove(page);
    }

    /**
     * Returns the number of pages within this ReportModel
     * @return page count
     */
    public int getPageCount() {
        return this.reportPages.size();
    }

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

    /**
     * Returns the subtitle of this ReportModel
     * @return subtitle
     */
    public String getSubtitle() {
        return this.subtitle;
    }

    /**
     * Returns the parameters used in creation of this ReportModel. May return
     * null.
     * @return Parameters used or null if not existing
     */
    public ReporterParams getParameters() {
        return this.parameters;
    }

    /** Returns the parameters as a ReportPageModel in textual format */
    public ReportPageModel getParametersAsPage() {

        ReportPageModel page = new ReportPageModel("Parameters",this.subtitle);
        page.addColumn("Name");
        page.addColumn("Value");
        page.addColumn("(Description as HTML)");
        for (FieldInstance f : this.parameters) {
            try {
                if (f.getValue()==null) continue;
                ArrayList<Object> row = new ArrayList<Object>(3);
                row.add(f.getName());
                row.add(f.getValue());
                row.add(f.getFullHtmlDescription());
                page.addRow(row);
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }
        }
        return page;
    }

    @Override
    public Iterator<ReportPageModel> iterator() {
        return this.reportPages.iterator();
    }

}
