/*
 * Copyright 2011 gitblit.com.
 *
 * 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 com.gitblit.wicket.pages;

import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.apache.wicket.PageParameters;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.markup.html.basic.Label;
import org.eclipse.jgit.lib.Repository;

import com.gitblit.models.Metric;
import com.gitblit.utils.MetricUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.CacheControl;
import com.gitblit.wicket.CacheControl.LastModified;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.charting.Chart;
import com.gitblit.wicket.charting.Charts;
import com.gitblit.wicket.charting.Flotr2Charts;

@CacheControl(LastModified.REPOSITORY)
public class MetricsPage extends RepositoryPage {

	public MetricsPage(PageParameters params) {
		super(params);
		Repository r = getRepository();
		if (StringUtils.isEmpty(objectId)) {
			add(new Label("branchTitle", getRepositoryModel().HEAD));
		} else {
			add(new Label("branchTitle", objectId));
		}
		Metric metricsTotal = null;
		List<Metric> metrics = MetricUtils.getDateMetrics(r, objectId, true, null, getTimeZone());
		metricsTotal = metrics.remove(0);
		if (metricsTotal == null) {
			add(new Label("branchStats", ""));
		} else {
			add(new Label("branchStats",
					MessageFormat.format(getString("gb.branchStats"), metricsTotal.count,
							metricsTotal.tag, getTimeUtils().duration(metricsTotal.duration))));
		}
		
		Charts charts =  new Flotr2Charts();
	
		add(WicketUtils.newBlankImage("commitsChart"));
		add(WicketUtils.newBlankImage("dayOfWeekChart"));
		add(WicketUtils.newBlankImage("authorsChart"));
			
		createLineChart(charts, "commitsChart", metrics);
		createBarChart(charts, "dayOfWeekChart", getDayOfWeekMetrics(r, objectId));
		createPieChart(charts, "authorsChart", getAuthorMetrics(r, objectId));
		
		add(new HeaderContributor(charts));

	}

	private void createLineChart(Charts charts, String id, List<Metric> metrics) {
		if ((metrics != null) && (metrics.size() > 0)) {
			
			Chart chart = charts.createLineChart(id, "", "day",
					getString("gb.commits"));
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
			String displayFormat = "MMM dd";
			if(metrics.size() > 0 && metrics.get(0).name.length() == 7){
				df = new SimpleDateFormat("yyyy-MM");
				displayFormat = "yyyy MMM";
			}
			df.setTimeZone(getTimeZone());
			chart.setDateFormat(displayFormat);
			for (Metric metric : metrics) {
				Date date;
				try {
					date = df.parse(metric.name);
				} catch (ParseException e) {
					logger.error("Unable to parse date: " + metric.name);
					return;
				}
				chart.addValue(date, (int)metric.count);
				if(metric.tag > 0 ){
					chart.addHighlight(date, (int)metric.count);
				}
			}
			charts.addChart(chart);	
		}
	}
	
	private void createPieChart(Charts charts, String id, List<Metric> metrics) {
		if ((metrics != null) && (metrics.size() > 0)) {
			
			Chart chart = charts.createPieChart(id, "", "day",
					getString("gb.commits"));
			for (Metric metric : metrics) {
				chart.addValue(metric.name, (int)metric.count);
			}
			charts.addChart(chart);	
		}
	}
	
	private void createBarChart(Charts charts, String id, List<Metric> metrics) {
		if ((metrics != null) && (metrics.size() > 0)) {
			Chart chart = charts.createBarChart(id, "", "day",
					getString("gb.commits"));
			for (Metric metric : metrics) {
				chart.addValue(metric.name, (int)metric.count);
			}
			charts.addChart(chart);	
		}
	}

	private List<Metric> getDayOfWeekMetrics(Repository repository, String objectId) {
		List<Metric> list = MetricUtils.getDateMetrics(repository, objectId, false, "E", getTimeZone());
		SimpleDateFormat sdf = new SimpleDateFormat("E");
		Calendar cal = Calendar.getInstance();

		List<Metric> sorted = new ArrayList<Metric>();
		int firstDayOfWeek = cal.getFirstDayOfWeek();
		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

		// rewind date to first day of week
		cal.add(Calendar.DATE, firstDayOfWeek - dayOfWeek);
		for (int i = 0; i < 7; i++) {
			String day = sdf.format(cal.getTime());
			for (Metric metric : list) {
				if (metric.name.equals(day)) {
					sorted.add(metric);
					list.remove(metric);
					break;
				}
			}
			cal.add(Calendar.DATE, 1);
		}
		return sorted;
	}

	private List<Metric> getAuthorMetrics(Repository repository, String objectId) {
		List<Metric> authors = MetricUtils.getAuthorMetrics(repository, objectId, true);
		Collections.sort(authors, new Comparator<Metric>() {
			@Override
			public int compare(Metric o1, Metric o2) {
				if (o1.count > o2.count) {
					return -1;
				} else if (o1.count < o2.count) {
					return 1;
				}
				return 0;
			}
		});
		if (authors.size() > 10) {
			return authors.subList(0, 9);
		}
		return authors;
	}

	@Override
	protected String getPageName() {
		return getString("gb.metrics");
	}

	@Override
	protected Class<? extends BasePage> getRepoNavPageClass() {
		return SummaryPage.class;
	}
}
