/* *******************************************************************
 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
 * All rights reserved. 
 * This program and the accompanying materials are made available 
 * under the terms of the Eclipse Public License v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *     PARC     initial implementation 
 * ******************************************************************/


package org.aspectj.weaver.patterns;

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

import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;


public class BasicTokenSource implements ITokenSource {
	private int index = 0;
	private IToken[] tokens;
	private ISourceContext sourceContext;

	public BasicTokenSource(IToken[] tokens, ISourceContext sourceContext) {
		this.tokens = tokens;
		this.sourceContext = sourceContext;
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int newIndex) {
		this.index = newIndex;
	}

	public IToken next() {
		try {
		    return tokens[index++];
		} catch (ArrayIndexOutOfBoundsException e) {
			return IToken.EOF;
		}
	}

	public IToken peek() {
		try {
		    return tokens[index];
		} catch (ArrayIndexOutOfBoundsException e) {
			return IToken.EOF;
		}
	}

	public IToken peek(int offset) {
		try {
		    return tokens[index+offset];
		} catch (ArrayIndexOutOfBoundsException e) {
			return IToken.EOF;
		}
	}

	public String toString() {
		StringBuffer buf = new StringBuffer();
		buf.append("[");
		for (int i = 0; i < tokens.length; i++) {
			IToken t = tokens[i];
			if (t == null)
				break;
			if (i > 0)
				buf.append(", ");
			buf.append(t.toString());
		}
		buf.append("]");
		return buf.toString();
	}
	
	
	//////////////////////////////////////////////////////
	// Convenience, maybe just for testing
	public static ITokenSource makeTokenSource(String input, ISourceContext context) {
		char[] chars = input.toCharArray();
		
		int i = 0;
		List<BasicToken> tokens = new ArrayList<BasicToken>();
		
		while (i < chars.length) {
			char ch = chars[i++];			
			switch(ch) {
				case ' ':
				case '\t':
				case '\n':
				case '\r':
					continue;
				case '*':
				case '(':
				case ')':
				case '+':
				case '[':
				case ']':
				case ',':
				case '!':
				case ':':
				case '@':
				case '<':
				case '>':
				case '=':
				case 	'?':
				    tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
				    continue;
				case '.':
					if ((i+2)<=chars.length) {
						// could be '...'
						char nextChar1 = chars[i];
						char nextChar2 = chars[i+1];
						if (ch==nextChar1 && ch==nextChar2) {
							// '...'
							tokens.add(BasicToken.makeIdentifier("...",i-1,i+1));
							i=i+2;
						} else {
							tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
						}
					} else {
						tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
					}
					continue;
				case '&':
					if ((i+1) <= chars.length && chars[i] != '&') {
						tokens.add(BasicToken.makeOperator(makeString(ch),i-1,i-1));
						continue;
					}
					// fall-through
				case '|':
				    if (i == chars.length) {
				    	throw new BCException("bad " + ch);
				    }
				    char nextChar = chars[i++];
				    if (nextChar == ch) {
				    	tokens.add(BasicToken.makeOperator(makeString(ch, 2), i-2, i-1));
				    } else {
				    	throw new RuntimeException("bad " + ch);
				    }
				    continue;
				    
				case '\"':
				    int start0 = i-1;
				    while (i < chars.length && !(chars[i]=='\"')) i++;
				    i += 1;
				    tokens.add(BasicToken.makeLiteral(new String(chars, start0+1, i-start0-2), "string", start0, i-1));
				    continue;
				default:
				    int start = i-1;
				    while (i < chars.length && Character.isJavaIdentifierPart(chars[i])) { i++; }
				    tokens.add(BasicToken.makeIdentifier(new String(chars, start, i-start), start, i-1));
				
			}
		}

		//System.out.println(tokens);
		
		return new BasicTokenSource((IToken[])tokens.toArray(new IToken[tokens.size()]), context);
	}

	private static String makeString(char ch) {
		return Character.toString(ch);
	}

	private static String makeString(char ch, int count) {
		// slightly inefficient ;-)
		char[] chars = new char[count];
		for (int i=0; i<count; i++) { chars[i] = ch; }
		return new String(chars);
	}
	public ISourceContext getSourceContext() {
		return sourceContext;
	}
	public void setSourceContext(ISourceContext context) {
		this.sourceContext = context;
	}

}
