/*
 * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com)
 *
 * Licensed 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 jef.tools.string;

import org.apache.commons.lang.ArrayUtils;

/**
 * 用于描述将一个Substring，用两个keyword分割成为五个部分的情形，
 * 所有的对象均用int型表示其在原String对象上的位置，从而避免String的大量内存操作
 */
public class StringSpliterEx {
	private Substring keyword1;
	private Substring keyword2;
	private Substring source;
	
	//------left-----| key1 | --middle- |key2|----right------  
	
	public static final int MODE_FROM_LEFT = 0;// 从左向右查找
	public static final int MODE_FROM_ENDS = 1;// 从两端向中间查找
	private int findMode = MODE_FROM_LEFT;

	public StringSpliterEx(Substring source) {
		this.source = source;
	}
	public StringSpliterEx(String source) {
		this.source = new Substring(source);
	}
	public Substring getKeyword1() {
		return keyword1;
	}
	public Substring getKeyword2() {
		return keyword2;
	}
	public Substring getSource() {
		return source;
	}
	public void setSource(Substring source) {
		this.source = source;
		this.keyword1=null;
		this.keyword2=null;
	}

	/**
	 * 获取左边部分
	 */
	public Substring getLeft() {
		if(keyword1==null && keyword2==null){
			return null;
		}else if(keyword1==null){
			return source.subAbsoultOffset(source.getStart(), keyword2.getStart());
		}else{
			return source.subAbsoultOffset(source.getStart(), keyword1.getStart());
		}
	}

	/**
	 * 获取右边部分
	 */
	public Substring getRight() {
		if(keyword1==null && keyword2==null){
			return null;
		}else if(keyword2==null){
			return source.subAbsoultOffset(keyword1.getEnd(),source.getEnd());
		}else{
			return source.subAbsoultOffset(keyword2.getEnd(),source.getEnd());
		}
		
	}

	/**
	 * 得到中间部分
	 * @return
	 */
	public Substring getMiddle() {
		if(keyword1==null && keyword2==null){
			return null;
		}else if(keyword1==null){
			return null;
		}else if(keyword2==null){
			return null;
		}else{
			return source.subAbsoultOffset(keyword1.getEnd(), keyword2.getStart());
		}
	}
	
	public static final int RESULT_NO_KEY=3;
	public static final int RESULT_BOTH_KEY=0;
	public static final int RESULT_KEY1_ONLY=1;
	public static final int RESULT_KEY2_ONLY=2;
	/**
	 * 设置一个值，查找，如果找到就形成keyStr对象，从而将对象可拆分为五个Substring.
	 * @param key1, key2
	 */
	public int setKeys(String key1,String key2) {
		StringSpliter sp=new StringSpliter(source);
		sp.setKey(key1);
		if(sp.getKeyword()!=null){
			this.keyword1=sp.getKeyword();
			sp=new StringSpliter(sp.getRight());
			if (findMode == MODE_FROM_ENDS) {
				sp.setMode(StringSpliter.MODE_FROM_RIGHT);
			}
			sp.setKey(key2);
			this.keyword2=sp.getKeyword();
			if(sp.getKeyword()!=null){
				return RESULT_BOTH_KEY;
			}else{
				return RESULT_KEY1_ONLY;
			}
		}else{
			if (findMode == MODE_FROM_ENDS) {
				sp.setMode(StringSpliter.MODE_FROM_RIGHT);	
			}
			sp.setKey(key2);
			this.keyword2=sp.getKeyword();
			if(sp.getKeyword()!=null){
				return RESULT_KEY2_ONLY;	
			}else{
				return RESULT_NO_KEY;	
			}
		}
		
	}

	public int setKeyOfAny(String[] key1,String[] key2) {
		StringSpliter sp=new StringSpliter(source);
		sp.setKeyOfAny(key1);
		if(sp.getKeyword()!=null){
			this.keyword1=sp.getKeyword();
			sp=new StringSpliter(sp.getRight());
			if (findMode == MODE_FROM_ENDS) {
				sp.setMode(StringSpliter.MODE_FROM_RIGHT);
			}
			sp.setKeyOfAny(key2);
			this.keyword2=sp.getKeyword();
			if(sp.getKeyword()!=null){
				return RESULT_BOTH_KEY;
			}else{
				return RESULT_KEY1_ONLY;
			}
		}else{
			if (findMode == MODE_FROM_ENDS) {
				sp.setMode(StringSpliter.MODE_FROM_RIGHT);	
			}
			sp.setKeyOfAny(key2);
			this.keyword2=sp.getKeyword();
			if(sp.getKeyword()!=null){
				return RESULT_KEY2_ONLY;	
			}else{
				return RESULT_NO_KEY;	
			}
		}
	}
	
	/**
	 * 和setKeyOfAny的区别在于，第一个匹配到的元素，在第二组key中只有位置相对的那个字串才有效。
	 * 如果 key1= "<","[" key2=">","]"， 当左<匹配后，右边只有>才能匹配。
	 * @param key1
	 * @param key2
	 * @return
	 */
	public int setKeyPairOfAny(String[] key1,String[] key2) {
		if(key1.length<key2.length){
			throw new IllegalArgumentException("the length between two input keys do not equals!");
		}
		StringSpliter sp=new StringSpliter(source);
		sp.setKeyOfAny(key1);
		if(sp.getKeyword()!=null){
			this.keyword1=sp.getKeyword();
			int n=ArrayUtils.indexOf(key1,this.keyword1.toString());
			if(n>key2.length-1){//key1找到，但没有指定可以匹配的key2
				return RESULT_KEY1_ONLY;
			}
			String realKey2=key2[n];
			sp=new StringSpliter(sp.getRight());
			if (findMode == MODE_FROM_ENDS) {
				sp.setMode(StringSpliter.MODE_FROM_RIGHT);
			}
			sp.setKey(realKey2);
			this.keyword2=sp.getKeyword();
			if(sp.getKeyword()!=null){
				return RESULT_BOTH_KEY;
			}else{
				return RESULT_KEY1_ONLY;
			}
		}else{
			if (findMode == MODE_FROM_ENDS) {
				sp.setMode(StringSpliter.MODE_FROM_RIGHT);	
			}
			sp.setKeyOfAny(key2);
			this.keyword2=sp.getKeyword();
			if(sp.getKeyword()!=null){
				return RESULT_KEY2_ONLY;	
			}else{
				return RESULT_NO_KEY;	
			}
		}
	}

	public int getMode() {
		return findMode;
	}

	public void setMode(int mode) {
		this.findMode = mode;
	}
}
