/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com

XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.

You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.

The terms of each license can be found in the source code repository:

GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.core.times; import gplx.*; import gplx.core.*;
public class DateAdp_parser {
	public int[] Parse_iso8651_like(String raw_str) {Parse_iso8651_like(tmp_rv, raw_str); return tmp_rv;} int[] tmp_rv = new int[7];
	public void Parse_iso8651_like(int[] rv, String raw_str) {
		byte[] raw_bry = Bry_.new_u8(raw_str);
		Parse_iso8651_like(rv, raw_bry, 0, raw_bry.length);
	}
	public void Parse_iso8651_like(int[] rv, byte[] src, int bgn, int end) {
		/*	1981-04-05T14:30:30.000-05:00	ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
			1981.04.05 14.30.30.000-05.00	ISO 8601 loose
			99991231_235959.999				gplx
			yyyy-MM-ddTHH:mm:ss.fffzzzz		Format String	*/
		int rv_len = rv.length;
		for (int i = 0; i < rv_len; i++)
			rv[i] = 0;	// .Clear
		int pos = bgn, rv_idx = 0, int_len = 0, max_len = max_lens[rv_idx];
		while (true) {
			int int_val = -1;
			byte b = pos < end ? src[pos] : Byte_ascii.Null;
			switch (b) {
				case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
				case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
					int_val = b - Byte_ascii.Num_0;	// convert ascii to val; EX: 49 -> 1
					int_len = int_bldr.Add(int_val);
					break;
			}
			if (	(int_val == -1 && int_len > 0)	// char is not number && number exists (ignore consecutive delimiters: EX: "1981  01")
				||	int_len == max_len) {			// max_len reached; necessary for gplxFormat
				rv[rv_idx++] = int_bldr.BldAndClear();
				if (rv_idx == 7) break;				// past frac; break;
				int_len = 0;
				max_len = max_lens[rv_idx];
			}
			if (pos == end) break;
			++pos;
		}
	}		
	int[] max_lens = new int[] {4/*y*/,2/*M*/,2/*d*/,2/*H*/,2/*m*/,2/*s*/,3/*S*/,0};
	IntBldr int_bldr = IntBldr.new_(4);
	public static DateAdp_parser new_() {return new DateAdp_parser();} DateAdp_parser() {}
}
class IntBldr {
	public int Add(char c) {
		if (idx > digitsLen - 1) throw Err_.new_missing_idx(idx, digitsLen);
		digits[idx++] = XbyChar(c);
		return idx;
	}
	public int Add(int i) {
		if (idx > digitsLen - 1) throw Err_.new_missing_idx(idx, digitsLen);
		digits[idx++] = i;
		return idx;
	}
	public int Parse(String raw) {
		ParseStr(raw);
		try {return Bld();}
		catch (Exception exc) {throw Err_.new_parse_exc(exc, int.class, raw);}
	}
	public boolean ParseTry(String raw) {
		ParseStr(raw);
		for (int i = 0; i < idx; i++)
			if (digits[i] < 0) return false;
		return true;
	}
	public int Bld() {
		int rv = 0, exponent = 1;
		for (int i = idx - 1; i > -1; i--) {
			int digit = digits[i];
			if (digit < 0) throw Err_.new_wo_type("invalid char", "char", (char)-digits[i], "ascii", -digits[i]);
			rv += digit * exponent;
			exponent *= 10;
		}
		return sign * rv;
	}
	public int BldAndClear() {
		int rv = Bld();
		this.Clear();
		return rv;
	}
	public void Clear() {idx = 0; sign = 1;}
	void ParseStr(String raw) {
		this.Clear();
		int rawLength = String_.Len(raw);
		for (int i = 0; i < rawLength; i++) {
			char c = String_.CharAt(raw, i);
			if (i == 0 && c == '-')
				sign = -1;
			else
				Add(c);
		}
	}
	int XbyChar(char c) {
		if (c == '0')		return 0; else if (c == '1')	return 1; else if (c == '2')	return 2; else if (c == '3')	return 3; else if (c == '4')	return 4;
		else if (c == '5')	return 5; else if (c == '6')	return 6; else if (c == '7')	return 7; else if (c == '8')	return 8; else if (c == '9')	return 9;
		else				return -(int)c;		// error handling: don't throw error; store ascii value in digit and throw if needed
	}
	int[] digits; int idx, digitsLen; int sign = 1;
	public static IntBldr new_(int digitsMax) {
		IntBldr rv = new IntBldr();
		rv.digits = new int[digitsMax];
		rv.digitsLen = digitsMax;
		return rv;
	}
}
