/*
 * Copyright 2007 Penn State University
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.psu.citeseerx.misc.charts;

import java.util.*;

import ChartDirector.*;

import edu.psu.citeseerx.dao2.*;
import edu.psu.citeseerx.dao2.logic.*;
import edu.psu.citeseerx.domain.*;
import edu.psu.citeseerx.repository.RepositoryMap;
import edu.psu.citeseerx.repository.UnknownRepositoryException;
import edu.psu.citeseerx.utility.FileNamingUtils;

/**
 * ChartBuilder implementation using ChartDirector.  Unfortunately,
 * ChartDirector is not free, but last I checked it allowed free usage
 * with a "Generated by ChartDirector" tag.
 *
 * @author Isaac Councill
 * @version $Rev$ $Date$
 */
public class CiteChartBuilderCD implements ChartBuilder {

    private static final int MAX_CITING = 5000;
    
    private CSXDAO csxdao;

    public void setCSXDAO(CSXDAO csxdao) {
        this.csxdao = csxdao;        
    }

    
    private CiteClusterDAO citedao;
    
    public void setCiteClusterDAO(CiteClusterDAO citedao) {
        this.citedao = citedao;        
    }
    
    
    private RepositoryMap repMap;
    
    public void setRepositoryMap(RepositoryMap repMap) {
        this.repMap = repMap;
    }
  
    
    /**
     * Builds a histogram for the supplied document and writes the chart to
     * the document's directory within the repository.
     * @param doc
     * @return A new histogram based on the provided document 
     */
    public XYChart buildChart(Document doc) {
        
        Long clusterid = doc.getClusterID();
        if (clusterid == null) {
            return null;
        }
        
        Integer year = null;
        try {
            year = new Integer(doc.getDatum(Document.YEAR_KEY));
        } catch (Exception e) { }
        
        java.util.List<ThinDoc> citingDocs =
            citedao.getCitingDocuments(clusterid, 0, MAX_CITING);
        DataPoint[] dataset = collectData(citingDocs, year);
        if (dataset == null || dataset.length <= 3) {
            return null;
        }
        
        double[] data = new double[dataset.length];
        int[] years = new int[dataset.length];
        String[] labels = new String[dataset.length];

        for (int i=0; i<dataset.length; i++) {
            data[i] = dataset[i].ncites;
            years[i] = dataset[i].year;
            labels[i] = Integer.toString(dataset[i].year);
        }
        
        double[] zeroedData = new double[years[years.length-1]+1];
        for (int i=0; i<years.length; i++) {
            zeroedData[years[i]] = data[i];
        }

        XYChart c = new XYChart(330, 255);
        int[] gradientArray = {
                0x000000, 0xc2dff4,
                0x000080, 0x0f7dd1,
                0x000100, 0x031c73
        };
        c.setPlotArea(45, 10, 270, 200,
                c.linearGradientColor2(60, 40, 60, 280, gradientArray),
                -1, 0xffffff, 0xffffff);
        //c.addBarLayer3(data).setBorderColor(Chart.Transparent,
        //        Chart.softLighting(Chart.Left) );
        c.addBarLayer(zeroedData, 0xFFA826).setBorderColor(Chart.Transparent,
                        Chart.softLighting(Chart.Left) );
        c.xAxis().setLinearScale(years[0], years[years.length-1]);
        //c.xAxis().setLinearScale2(0, years.length-1, labels);
        //c.xAxis().setLabels(labels);
        //c.xAxis().setTickOffset(0.5);
        c.xAxis().setTitle("Year", "Arial Bold", 10);
        //c.xAxis().setTickDensity(100);
        //c.xAxis().setLinearScale3();
        c.yAxis().setTitle("Citations", "Arial Bold", 10);
        c.yAxis().setMinTickInc(1);
        //c.yAxis().setTickDensity(20);
        c.xAxis().setLabelStyle("Arial Bold", 8); 
        c.yAxis().setLabelStyle("Arial Bold", 8);
        c.xAxis().setWidth(2); 
        c.yAxis().setWidth(2);

        BarLayer layer = c.addBarLayer2(Chart.Stack);
        layer.addDataSet(data, 0xff6600);
        
        return c;
        
    }
    
    private DataPoint[] collectData(java.util.List<ThinDoc> docs,
            Integer baseYear) {
        
        int maxyear = -1;
        int minyear = 999999;
        
        Calendar now = Calendar.getInstance();
        int currentYear = now.get(Calendar.YEAR);

        boolean found = false;
        
        HashMap<Integer,DataPoint> data = new HashMap<Integer,DataPoint>();
        for (ThinDoc doc : docs) {
            try {
                Integer year = new Integer(doc.getYear());
                if (year.intValue() < 1930 ||
                        (baseYear != null && year < baseYear) ||
                        year.intValue() > currentYear + 2) {
                    continue;
                }
                DataPoint point;
                if (data.containsKey(year)) {
                    point = data.get(year);
                } else {
                    point = new DataPoint(year.intValue());
                    data.put(year, point);
                }
                point.ncites++;
                if (year > maxyear) {
                    maxyear = year;
                }
                if (year < minyear) {
                    minyear = year;
                }
                found = true;
            } catch (Exception e) { }
        }

        if (!found) {
            return null;
        }

        DataPoint[] datalist = new DataPoint[maxyear-minyear+1];
        for (int i=minyear; i<=maxyear; i++) {
            Integer key = new Integer(i);
            if (data.containsKey(key)) {
                datalist[i-minyear] = data.get(key);
            } else {
                DataPoint point = new DataPoint(i);
                point.ncites = 0;
                datalist[i-minyear] = point;
            }
        }
        
        return datalist;
        
    } //- collectData


    /* (non-Javadoc)
     * @see edu.psu.citeseerx.misc.charts.ChartBuilder#buildAll()
     */
    public void buildAll() throws UnknownRepositoryException {
        
        String lastDoi = "0.0.0.0.0";
        int amount = 200;
        
        while(true) {
            java.util.List<String> dois = csxdao.getDOIs(lastDoi, amount);
            if (dois.isEmpty()) {
                break;
            }
            for (String doi : dois) {
                lastDoi = doi;
                if (!csxdao.checkChartUpdateRequired(doi)) {
                    continue;
                }
                Document doc = csxdao.getDocumentFromDB(doi, false, false);
                if (doc.getNcites() < 2) {
                    continue;
                }
                XYChart chart = buildChart(doc);
                if (chart != null) {
                    String repID =
                        doc.getFileInfo().getDatum(DocumentFileInfo.REP_ID_KEY);
                    String relPath = FileNamingUtils.getDirectoryFromDOI(doi);
                    relPath += "citechart.png";
                    String path = repMap.buildFilePath(repID, relPath);
                    System.out.println(path);
                    chart.makeChart(path);
                    csxdao.insertChartUpdate(doi, doc.getNcites(), null);
                }
            }
        }
        
    }  //- buildAll
        
}  //- class CiteChartBuilderCD

