package org.postgresforest.vm;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.util.ArrayList;

public class SqlTokenizer extends StreamTokenizer {

    private boolean pushedBack;

    private boolean m_endFls = false;
	
	public SqlTokenizer(InputStream is) {
		super(is);
		m_inSingleQuotes = false;
		m_inDoubleQuotes = false;
		m_inParen = 0;
		m_fragmentList = new ArrayList(15);
	}

	public SqlTokenizer(Reader r) {
		super(r);
		m_inSingleQuotes = false;
		m_inDoubleQuotes = false;
		m_inParen = 0;
		m_fragmentList = new ArrayList(15);
	}

	
	

    protected StringBuffer m_sqlFragment = new StringBuffer();
	private boolean m_inSingleQuotes;
	private boolean m_inDoubleQuotes;
	private int m_inParen;
	private ArrayList m_fragmentList;
    
	public int nextToken() throws IOException {

		
		int token = super.nextToken();
		if (pushedBack) {
		    pushedBack = false;
		    return token;
		}

        
		if(token == StreamTokenizer.TT_WORD){
			
			m_sqlFragment.append(sval);
			
		}else if(token == StreamTokenizer.TT_EOF){
			if(!m_endFls){
				m_fragmentList.add(m_sqlFragment.toString());
				m_endFls = true;
			}

		}else{
			
	        switch (token)
	        {
	        case '\'':
	            m_inSingleQuotes = !m_inDoubleQuotes && !m_inSingleQuotes;
	        	m_sqlFragment.append((char)token);
	            break;

	        case '"':
	            m_inDoubleQuotes = !m_inSingleQuotes && !m_inDoubleQuotes;
	        	m_sqlFragment.append((char)token);
	            break;

	        case '?':
	            if (!m_inSingleQuotes && !m_inDoubleQuotes)
	            {
	                m_fragmentList.add(m_sqlFragment.toString());
	                m_sqlFragment.delete(0, m_sqlFragment.length());
	            }else{
		        	m_sqlFragment.append((char)token);
	            }
	            break;

	        case '(':
	            if (!m_inSingleQuotes && !m_inDoubleQuotes)
	                    m_inParen++;
	        	m_sqlFragment.append((char)token);
	            break;

	        case ')':
	            if (!m_inSingleQuotes && !m_inDoubleQuotes)
	                    m_inParen--;
	        	m_sqlFragment.append((char)token);
	            break;

//	        case ';':
//	            if (!m_inSingleQuotes && !m_inDoubleQuotes && m_inParen == 0)
//	            {
//					if(m_sqlFragment.length() !=0 ){
//		                m_fragmentList.add(m_sqlFragment.toString());
//					}
//	                m_sqlFragment.delete(0, m_sqlFragment.length());
//	            }else{
//	            	m_sqlFragment.append((char)token);
//	            }
//	            break;

	        default:
	        	m_sqlFragment.append((char)token);
	            break;
	        }
			
			
		}
		
		return token;
		
	}

	public void pushBack() {

		super.pushBack();
   	    pushedBack = true;

	}


	public int getParamNum() {
		
		return m_fragmentList.size();
	}
	
	
	
	
   public static void main(String[] args) {

//       String a = "SELECT name,count(uid) FROM t1 WHERE uid IN ( SELECT uid FROM t2 WHERE uid>1000 )";
       String a = "SELECT name,count(?) FROM t1 WHERE uid IN ( SELECT uid FROM t2 WHERE uid>1000 ) and item_cd='?' ant item_name=?";

	        for (int i = 0; i < 1000; i++) {
//	            test2(a);
	            test1(a);
	        }

    }

	    static private void test1(String a) {
	        java.io.StringReader fr = new java.io.StringReader(a);
	        SqlTokenizer m_tokenizer = new SqlTokenizer(fr);

	        //Ver1.1R4
	        m_tokenizer.resetSyntax();
	        m_tokenizer.wordChars('a', 'z');
	        m_tokenizer.wordChars('A', 'Z');
	        m_tokenizer.wordChars('_', '_');
	        m_tokenizer.wordChars('.', '.');
	        m_tokenizer.wordChars('0', '9');

	        m_tokenizer.ordinaryChar('/');//BUG '/'があると文字列終了とみなしていたので、文字に追加

	        m_tokenizer.eolIsSignificant(true);

	        int token = java.io.StreamTokenizer.TT_EOF;
	        StringBuffer b = new StringBuffer();
	        boolean flg = true;
	        try {
	            while ((token = m_tokenizer.nextToken()) != java.io.StreamTokenizer.TT_EOF) {
	    	        System.out.println(m_tokenizer.getParamNum());
	            	
	                if (token == java.io.StreamTokenizer.TT_WORD) {
	
	                    b.append(m_tokenizer.sval);
	                    if(flg){
	                    	m_tokenizer.pushBack();
	                    }
	                    flg = !flg;
	                    	
	                    	
	                    
	                }else
	                    b.append((char)token);

	            }
	        } catch (IOException e) {
	            // TODO 自動生成された catch ブロック
	            e.printStackTrace();
	        }
	        
	        System.out.println(m_tokenizer.m_fragmentList);
	        System.out.println(b);

	    }

		public ArrayList getFragmentList() {
			return m_fragmentList;
		}
	
	
}
