package info.bukova.isspst.ui.limits;

import info.bukova.isspst.StringUtils;
import info.bukova.isspst.data.Limit;
import info.bukova.isspst.data.Workgroup;
import info.bukova.isspst.services.invoicing.InvoicingService;
import info.bukova.isspst.services.limits.LimitService;
import info.bukova.isspst.services.workgroups.WorkgroupService;
import info.bukova.isspst.ui.ListViewModel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer3D;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.RectangleEdge;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.select.annotation.WireVariable;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class LimitsList extends ListViewModel<Limit> {

	@WireVariable
	private LimitService limitService;
	@WireVariable
	private InvoicingService invoicingService;
	@WireVariable
	private WorkgroupService workgroupService;
	private Map<Limit, BigDecimal> spent;
	private RenderedImage chart;

	@Init(superclass = true)
	public void init() {
		service = limitService;
		dataClass = Limit.class;
		formZul = "limitForm.zul";
		//dataFilter = new MUnitFilter(getFilterTemplate());
		genSpent();
	}

	public Map<Limit, BigDecimal> getSpent() {
		if (spent != null && !getDataList().isEmpty()) {
			for (Limit l : spent.keySet()) {
				if (!l.getSeason().equals(getDataList().get(0).getSeason())) {
					spent = null;
				}
				break;
			}
		}

		if (spent != null && spent.keySet().size() < getDataList().size()) {
			spent = null;
		}

		if (spent != null) {
			return spent;
		}

		spent = new HashMap<Limit, BigDecimal>();
		for (Limit l : getDataList()) {
			spent.put(l, invoicingService.totalInvoicedForWorkgroupAndSeason(l.getWorkgroup(), getSelSeason()));
		}

		return spent;
	}

	private void genSpent() {
		spent = new HashMap<Limit, BigDecimal>();
		for (Limit l : getDataList()) {
			spent.put(l, invoicingService.totalInvoicedForWorkgroupAndSeason(l.getWorkgroup(), getSelSeason()));
		}
	}

	private void genCharts() {
		DefaultCategoryDataset dataSet = new DefaultCategoryDataset();

		for (Workgroup wg : workgroupService.getWorkgroups()) {
			Limit limit = null;
			for (Limit l : getDataList()) {
				if (l.getWorkgroup().equals(wg)) {
					limit = l;
					break;
				}
			}

			dataSet.addValue(limit == null ? null : limit.getLimit(), StringUtils.localize("LimitsLimit"), wg.getFullName());
			dataSet.addValue(invoicingService.totalInvoicedForWorkgroupAndSeason(wg, getSelSeason()), StringUtils.localize("LimitsSpent"), wg.getFullName());
		}

		JFreeChart jfChart = ChartFactory.createBarChart3D(StringUtils.localize("LimitsChartTitle"), StringUtils.localize("LimitsWorkgroup"),
				StringUtils.localize("LimitsAmount"), dataSet, PlotOrientation.HORIZONTAL, true, false, false);
		CategoryPlot plot = (CategoryPlot) jfChart.getPlot();
        BarRenderer3D renderer = (BarRenderer3D) plot.getRenderer();
		renderer.setSeriesPaint(0, Color.GREEN);
		renderer.setSeriesPaint(1, Color.RED);

		LegendTitle legend = jfChart.getLegend();
		legend.setPosition(RectangleEdge.RIGHT);

		try {
				chart = ImageIO.read(new ByteArrayInputStream(ChartUtilities.encodeAsPNG(jfChart.createBufferedImage(1000, 400))));
		} catch (IOException e) {
				chart = null;
				e.printStackTrace();
		}
	}

	public RenderedImage getChart() {
		genCharts();
		return chart;
	}

	@Override
	@GlobalCommand
	@NotifyChange({ "dataList", "dataBean", "ableToDelete", "chart", "spent" })
	public void refresh() {
		genSpent();
		super.refresh();
	}
}
