/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.epam.dlab.core.parser;

import java.util.ArrayList;
import java.util.List;

import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.StringUtils;

import com.epam.dlab.core.AdapterBase;
import com.epam.dlab.core.FilterBase;
import com.epam.dlab.core.ModuleBase;
import com.epam.dlab.core.aggregate.AggregateGranularity;
import com.epam.dlab.core.aggregate.DataAggregator;
import com.epam.dlab.exceptions.AdapterException;
import com.epam.dlab.exceptions.InitializationException;
import com.epam.dlab.exceptions.ParseException;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects.ToStringHelper;

/** Abstract module of parser.<br>
 * See description of {@link ModuleBase} how to create your own parser.
 */
public abstract class ParserBase extends ModuleBase {
	
	/** Default character used for decimal sign. */
	public static final char DECIMAL_SEPARATOR_DEFAULT = '.';
	
	/** Default character used for thousands separator. */
	public static final char DECIMAL_GROUPING_SEPARATOR_DEFAULT = ' ';
	
	/** Name of key for date report data. */
	public static final String DATA_KEY_START_DATE = "ParserBase.maxStartDate";

	
	/** Mapping columns from source format to target. */
	@JsonProperty
	private String columnMapping = null;
	
	/** Where condition for filtering the source data. */
	@JsonProperty
	private String whereCondition = null;
	
	/** How to aggregate the parsed data. */
	@JsonProperty
	@NotNull
	private AggregateGranularity aggregate = AggregateGranularity.NONE;
	
	/** Character used for decimal sign of source data. */
	@JsonProperty
	@NotNull
	private char decimalSeparator = DECIMAL_SEPARATOR_DEFAULT;
	
	/** Character used for thousands separator of source data. */
	@JsonProperty
	@NotNull
	private char groupingSeparator = DECIMAL_GROUPING_SEPARATOR_DEFAULT;


	/** Adapter for reading source data. */
	@JsonIgnore
	private AdapterBase adapterIn;
	
	/** Adapter for writing converted data. */
	@JsonIgnore
	private AdapterBase adapterOut;
	
	/** Filter for source and converted data. */
	@JsonIgnore
	private FilterBase filter;


	/** Column meta information. */
	@JsonIgnore
	private ColumnMeta columnMeta;
	
	/** Condition for filtering the source data. */
	@JsonIgnore
	private ConditionEvaluate condition;
	
	/** Aggregator of billing report.*/
	@JsonIgnore
	private DataAggregator aggregator;
	
	/** Common format helper. */
	@JsonIgnore
	private CommonFormat commonFormat;

	/** Parser statistics. */
	@JsonIgnore
	private final List<ParserStatistics> statistics = new ArrayList<>();
	
	/** Current parser statistics. */
	@JsonIgnore
	ParserStatistics currentStatistics = null; 
	
	
	/** Return mapping columns from source format to target. */
	public String getColumnMapping() {
		return columnMapping;
	}

	/** Set mapping columns from source format to target. */
	public void setColumnMapping(String columnMapping) {
		this.columnMapping = columnMapping;
	}

	/** Return where condition for filtering the source data. */
	public String getWhereCondition() {
		return whereCondition;
	}

	/** Set where condition for filtering the source data. */
	public void setWhereCondition(String whereCondition) {
		this.whereCondition = whereCondition;
	}

	/** Return how to aggregate the parsed data. */
	public AggregateGranularity getAggregate() {
		return aggregate;
	}

	/** Set how to aggregate the parsed data.
	 * @throws InitializationException */
	public void setAggregate(String aggregate) throws InitializationException {
		if (aggregate == null) {
			throw new InitializationException("Property aggregate cannot be null");
		}
		AggregateGranularity value = AggregateGranularity.of(aggregate);
        if (value == null) {
        	throw new InitializationException("Invalid value \"" + aggregate + "\" for property aggregate. " +
					"Should be one of: " + StringUtils.join(AggregateGranularity.values(), ", "));
        }
		this.aggregate = value;
	}

	/** Return character used for decimal sign of source data. */
	public char getDecimalSeparator() {
		return decimalSeparator;
	}
	
	/** Set character used for decimal sign of source data. */
	public void setDecimalSeparator(char decimalSeparator) {
		this.decimalSeparator = decimalSeparator;
	}
	
	/** Return character used for thousands separator of source data. */
	public char getGroupingSeparator() {
		return groupingSeparator;
	}
	
	/** Set character used for thousands separator of source data. */
	public void setGroupingSeparator(char groupingSeparator) {
		this.groupingSeparator = groupingSeparator;
	}
	
	
	/** Return the adapter for reading source data. */
	public AdapterBase getAdapterIn() {
		return adapterIn;
	}

	/** Return the adapter for writing converted data. */
	public AdapterBase getAdapterOut() {
		return adapterOut;
	}
	
	/** Return the filter for source and converted data. */
	public FilterBase getFilter() {
		return filter;
	}

	/** Return the column meta information. */
	public ColumnMeta getColumnMeta() {
		return columnMeta;
	}
	
	/** Return the condition for filtering the source data. */
	public ConditionEvaluate getCondition() {
		return condition;
	}
	
	/** Return the aggregator of billing report.*/
	public DataAggregator getAggregator() {
		return aggregator;
	}
	
	/** Return the common format helper. */
	public CommonFormat getCommonFormat() {
		return commonFormat;
	}
	
	/** Return the parser statistics. */
	public List<ParserStatistics> getStatistics() {
		return statistics;
	}
	
	/** Add and return the new instance for statistics.
	 * @param entryName the name of new entry.
	 */
	public ParserStatistics addStatistics(String entryName) {
		currentStatistics = new ParserStatistics(entryName);
		statistics.add(currentStatistics);
		return currentStatistics;
	}
	
	/** Return the current parser statistics. */
	public ParserStatistics getCurrentStatistics() {
		return currentStatistics;
	}

	
	/** Initialize the parser.
	 * @throws InitializationException
	 */
	public abstract void initialize()  throws InitializationException;
	
	/** Parse the source data to common format and write it to output adapter.
	 * @throws InitializationException
	 * @throws AdapterException
	 * @throws ParseException
	 */
	public abstract void parse() throws InitializationException, AdapterException, ParseException;
	
	/** Build parser from given modules.
	 * @param adapterIn the adapter for reading source data.
	 * @param adapterOut the adapter for writing converted data.
	 * @param filter the filter for source and converted data. May be <b>null<b>.
	 */
	public ParserBase build(AdapterBase adapterIn, AdapterBase adapterOut, FilterBase filter) {
		this.adapterIn = adapterIn;
		this.adapterOut = adapterOut;
		if (filter != null) {
			filter.setParser(this);
		}
		this.filter = filter;
		return this;
	}
	
	
	/** Initialize ParserBase.
	 * @param header - the header of source data.
	 * @throws InitializationException
	 * @throws AdapterException
	 */
	protected void init(List<String> header) throws InitializationException, AdapterException {
		columnMeta = new ColumnMeta(columnMapping, header);
		if (whereCondition != null) {
			if (columnMeta.getSourceColumnNames() == null) {
				throw new InitializationException("To use the whereCondition property you must specify and have the header of source data");
			}
			condition = new ConditionEvaluate(columnMeta.getSourceColumnNames(), whereCondition);
		} else {
			condition = null;
		}
		commonFormat = new CommonFormat(columnMeta, decimalSeparator, groupingSeparator);

		if (aggregate != AggregateGranularity.NONE) {
			aggregator = new DataAggregator(aggregate);
		}

		if (getAdapterOut().isWriteHeader()) {
			getAdapterOut().writeHeader(columnMeta.getTargetColumnNames());
		}
	}
	
	
	/** Return the index of source column by column name. 
	 * @param columnName the name of column.
	 * @throws InitializationException
	 */
	public int getSourceColumnIndexByName(String columnName) throws InitializationException {
		return ColumnMeta.getColumnIndexByName(columnName, columnMeta.getSourceColumnNames());
	}
	
	
	@Override
	public ToStringHelper toStringHelper(Object self) {
    	return super.toStringHelper(self)
    			.add("adapterIn", (adapterIn == null ? null : adapterIn.getType()))
    			.add("adapterOut", (adapterOut == null ? null : adapterOut.getType()))
    			.add("filter", (filter == null ? null : filter.getType()))
    			.add("columnMapping", columnMapping)
    			.add("whereCondition", whereCondition)
    			.add("aggregate", aggregate)
    			.add("decimalSeparator", decimalSeparator)
    			.add("groupingSeparator", groupingSeparator);
    }
}
