/*******************************************************************************
 * Copyright (c) 2008, 2019 SWTChart project.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 * yoshitaka - initial API and implementation
 * Frank Buloup = Internationalization
 *******************************************************************************/
package org.eclipse.swtchart.internal.series;

import java.text.DecimalFormat;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swtchart.ISeriesLabel;
import org.eclipse.swtchart.internal.Util;

/**
 * A series label.
 */
public class SeriesLabel implements ISeriesLabel {

	/** the visibility state of series label */
	private boolean isVisible;
	/** the series label font */
	protected Font font;
	/** the series label color */
	protected Color color;
	/** the format for series label */
	private String format;
	/** the formats for series labels */
	private String[] formats;
	/** the default label color */
	private static final int DEFAULT_COLOR = SWT.COLOR_BLACK;
	/** the default font */
	private static final Font DEFAULT_FONT = Display.getDefault().getSystemFont();
	/** the default label format */
	private static final String DEFAULT_FORMAT = "#.###########"; //$NON-NLS-1$

	/**
	 * Constructor.
	 */
	public SeriesLabel() {
		font = DEFAULT_FONT;
		color = Display.getDefault().getSystemColor(DEFAULT_COLOR);
		isVisible = false;
		format = DEFAULT_FORMAT;
		formats = new String[0];
	}

	@Override
	public String getFormat() {

		return format;
	}

	@Override
	public void setFormat(String format) {

		if(format == null) {
			this.format = DEFAULT_FORMAT;
		} else {
			this.format = format;
		}
	}

	@Override
	public String[] getFormats() {

		String[] copiedFormats = new String[formats.length];
		System.arraycopy(formats, 0, copiedFormats, 0, formats.length);
		return copiedFormats;
	}

	@Override
	public void setFormats(String[] formats) {

		if(formats == null) {
			this.formats = new String[0];
			return;
		}
		this.formats = new String[formats.length];
		System.arraycopy(formats, 0, this.formats, 0, formats.length);
	}

	@Override
	public Color getForeground() {

		return color;
	}

	@Override
	public void setForeground(Color color) {

		if(color != null && color.isDisposed()) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		if(color == null) {
			this.color = Display.getDefault().getSystemColor(DEFAULT_COLOR);
		} else {
			this.color = color;
		}
	}

	@Override
	public Font getFont() {

		if(font.isDisposed()) {
			font = DEFAULT_FONT;
		}
		return font;
	}

	@Override
	public void setFont(Font font) {

		if(font != null && font.isDisposed()) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		if(font == null) {
			this.font = DEFAULT_FONT;
		} else {
			this.font = font;
		}
	}

	@Override
	public boolean isVisible() {

		return isVisible;
	}

	@Override
	public void setVisible(boolean visible) {

		this.isVisible = visible;
	}

	/**
	 * Draws series label.
	 *
	 * @param gc
	 *            the GC object
	 * @param h
	 *            the horizontal coordinate to draw label
	 * @param v
	 *            the vertical coordinate to draw label
	 * @param ySeriesValue
	 *            the Y series value
	 * @param seriesIndex
	 *            the series index
	 * @param alignment
	 *            the alignment of label position (SWT.CENTER or SWT.BOTTOM)
	 */
	protected void draw(GC gc, int h, int v, double ySeriesValue, int seriesIndex, int alignment) {

		if(!isVisible) {
			return;
		}
		Color oldForeground = gc.getForeground();
		gc.setForeground(color);
		gc.setFont(getFont());
		// get format
		String format1 = format;
		if(formats.length > seriesIndex) {
			format1 = formats[seriesIndex];
		}
		if(format1 == null || format1.equals("")) { //$NON-NLS-1$
			return;
		}
		// get text
		String text;
		if(isDecimalFormat(format1)) {
			text = new DecimalFormat(format1).format(ySeriesValue);
		} else {
			text = format1.replaceAll("'", ""); //$NON-NLS-1$ //$NON-NLS-2$
		}
		// draw label
		if(alignment == SWT.CENTER) {
			Point p = Util.getExtentInGC(font, text);
			gc.drawString(text, (int)(h - p.x / 2d), (int)(v - p.y / 2d), true);
		} else if(alignment == SWT.BOTTOM) {
			gc.drawString(text, h, v, true);
		}
		gc.setForeground(oldForeground);
	}

	/**
	 * Gets the state indicating if decimal format is given.
	 *
	 * @param text
	 *            the text to be checked
	 * @return true if decimal format is given
	 */
	private static boolean isDecimalFormat(String text) {

		StringBuilder nonEscapedPart = new StringBuilder();
		String[] elements = text.split("'"); //$NON-NLS-1$
		if(elements != null) {
			for(int i = 0; i < elements.length; i += 2) {
				nonEscapedPart.append(elements[i]);
			}
		}
		if(nonEscapedPart.indexOf("#") == -1 && nonEscapedPart.indexOf("0") == -1) { //$NON-NLS-1$ //$NON-NLS-2$
			return false;
		}
		return true;
	}
}
