/* ====================================================================
   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 org.apache.poi.ss.formula.function;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.poi.ss.formula.ptg.Ptg;

/**
 * Converts the text meta-data file into a <tt>FunctionMetadataRegistry</tt>
 *
 * @author Josh Micich
 */
final class FunctionMetadataReader {

	private static final String METADATA_FILE_NAME = "functionMetadata.txt";

	/** plain ASCII text metadata file uses three dots for ellipsis */
	private static final String ELLIPSIS = "...";

	private static final Pattern TAB_DELIM_PATTERN = Pattern.compile("\t");
	private static final Pattern SPACE_DELIM_PATTERN = Pattern.compile(" ");
	private static final byte[] EMPTY_BYTE_ARRAY = { };

	private static final String[] DIGIT_ENDING_FUNCTION_NAMES = {
		// Digits at the end of a function might be due to a left-over footnote marker.
		// except in these cases
		"LOG10", "ATAN2", "DAYS360", "SUMXMY2", "SUMX2MY2", "SUMX2PY2",
	};
	private static final Set<String> DIGIT_ENDING_FUNCTION_NAMES_SET = new HashSet<String>(Arrays.asList(DIGIT_ENDING_FUNCTION_NAMES));

	public static FunctionMetadataRegistry createRegistry() {
	    try {
    		InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME);
    		if (is == null) {
    			throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
    		}
    
    		try {
        		BufferedReader br;
        		try {
        			br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
        		} catch(UnsupportedEncodingException e) {
        			throw new RuntimeException(e);
        		}
        		
        		try {
        		    FunctionDataBuilder fdb = new FunctionDataBuilder(400);
        
        			while (true) {
        				String line = br.readLine();
        				if (line == null) {
        					break;
        				}
        				if (line.length() < 1 || line.charAt(0) == '#') {
        					continue;
        				}
        				String trimLine = line.trim();
        				if (trimLine.length() < 1) {
        					continue;
        				}
        				processLine(fdb, line);
        			}

        			return fdb.build();
        		} finally {
        		    br.close();
        		}
    		} finally {
    		    is.close();
    		}
        } catch (IOException e) {
            throw new RuntimeException(e);
	    } 
	}

	private static void processLine(FunctionDataBuilder fdb, String line) {

		String[] parts = TAB_DELIM_PATTERN.split(line, -2);
		if(parts.length != 8) {
			throw new RuntimeException("Bad line format '" + line + "' - expected 8 data fields");
		}
		int functionIndex = parseInt(parts[0]);
		String functionName = parts[1];
		int minParams = parseInt(parts[2]);
		int maxParams = parseInt(parts[3]);
		byte returnClassCode = parseReturnTypeCode(parts[4]);
		byte[] parameterClassCodes = parseOperandTypeCodes(parts[5]);
		// 6 isVolatile
		boolean hasNote = parts[7].length() > 0;

		validateFunctionName(functionName);
		// TODO - make POI use isVolatile
		fdb.add(functionIndex, functionName, minParams, maxParams,
				returnClassCode, parameterClassCodes, hasNote);
	}


	private static byte parseReturnTypeCode(String code) {
		if(code.length() == 0) {
			return Ptg.CLASS_REF; // happens for GETPIVOTDATA
		}
		return parseOperandTypeCode(code);
	}

	private static byte[] parseOperandTypeCodes(String codes) {
		if(codes.length() < 1) {
			return EMPTY_BYTE_ARRAY; // happens for GETPIVOTDATA
		}
		if(isDash(codes)) {
			// '-' means empty:
			return EMPTY_BYTE_ARRAY;
		}
		String[] array = SPACE_DELIM_PATTERN.split(codes);
		int nItems = array.length;
		if(ELLIPSIS.equals(array[nItems-1])) {
			// final ellipsis is optional, and ignored
			// (all unspecified params are assumed to be the same as the last)
			nItems --;
		}
		byte[] result = new byte[nItems];
		for (int i = 0; i < nItems; i++) {
			result[i] = parseOperandTypeCode(array[i]);
		}
		return result;
	}

	private static boolean isDash(String codes) {
		if(codes.length() == 1) {
			switch (codes.charAt(0)) {
				case '-':
					return true;
			}
		}
		return false;
	}

	private static byte parseOperandTypeCode(String code) {
		if(code.length() != 1) {
			throw new RuntimeException("Bad operand type code format '" + code  + "' expected single char");
		}
		switch(code.charAt(0)) {
			case 'V': return Ptg.CLASS_VALUE;
			case 'R': return Ptg.CLASS_REF;
			case 'A': return Ptg.CLASS_ARRAY;
		}
		throw new IllegalArgumentException("Unexpected operand type code '" + code + "' (" + (int)code.charAt(0) + ")");
	}

	/**
	 * Makes sure that footnote digits from the original OOO document have not been accidentally
	 * left behind
	 */
	private static void validateFunctionName(String functionName) {
		int len = functionName.length();
		int ix = len - 1;
		if (!Character.isDigit(functionName.charAt(ix))) {
			return;
		}
		while(ix >= 0) {
			if (!Character.isDigit(functionName.charAt(ix))) {
				break;
			}
			ix--;
		}
		if(DIGIT_ENDING_FUNCTION_NAMES_SET.contains(functionName)) {
			return;
		}
		throw new RuntimeException("Invalid function name '" + functionName
				+ "' (is footnote number incorrectly appended)");
	}

	private static int parseInt(String valStr) {
		try {
			return Integer.parseInt(valStr);
		} catch (NumberFormatException e) {
			throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
		}
	}
}
