package ca.oson.json.path;

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

import ca.oson.json.path.Step.Type;
import ca.oson.json.util.ArrayToJsonMap;

public class XPathProcessor extends PathProcessor {

	public XPathProcessor(String xpath) {
		super(xpath);
	}
	
	
	/*
	 * Major predicate processing
	 */
	private Filter processFilter(String raw) {
		Filter filter = new Filter(raw);
		
		
		return filter;
	}
	
	private Step processStep(String raw) {
		String name = "";
		
		int i = raw.indexOf("[");
		
		if (i > -1) {
			name = raw.substring(0, i).trim();
			
		} else {
			name = raw;
		}

		Step step = new Step(raw, name);
		
		List<Filter> predicates = new ArrayList<>();
		

		while (i > -1) {
			raw = raw.substring(i+1).trim();
			
			i = raw.indexOf("]");

			Filter filter = processFilter(raw.substring(0, i).trim());
			
			predicates.add(filter);
			
			i = raw.indexOf("[", i+1);
		}
		
		return step;
	}

	
	@Override
	public List<Step> process() {
		// first clean up unncessary phrases
		Map<String, Object> cleanupMap = ArrayToJsonMap.array2Map(new String[] {
			"child::", "",
			"descendant-or-self::node()", "",
			"self::node()", "."
		});
		
		for (String key: cleanupMap.keySet()) {
			String replacement = cleanupMap.get(key).toString();
			xpath.replaceAll(key, replacement);
		}

		//int length = xpath.length();
		int currentPos = 0;
		
		Step current = null;
		List<Step> steps = new ArrayList<>();
		
		String stepDelimiter = "/";
		String oneOrMore = "//";
		String any = "*";
		
		if (xpath.startsWith(oneOrMore)) {
			current = Step.getInstance(Type.ONE_OR_MORE);
			steps.add(current);
			currentPos += 2;
		} else if (xpath.startsWith(stepDelimiter)) {
			current = Step.getInstance(Type.ROOT);
			steps.add(current);
			currentPos++;
		}

		
		String[] splitted = xpath.substring(currentPos).split(stepDelimiter);

		for (int i = 0; i < splitted.length; i++) {
			String raw = splitted[i].trim();
			
			if (raw.equals("")) {
				current = Step.getInstance(Type.ONE_OR_MORE);
				
			} else if (raw.equals(any)) {
				current = Step.getInstance(Type.ANY);
				
			} else {
				current = processStep(raw);
			}
			
			steps.add(current);
		}

		return steps;
	}

}

@@ -1180,16 +1180,43 @@
 ()%22, %22.%22
+,%0A%09%09%09%22parent::node()%22, %22..%22
 %0A%09%09%7D);%0A%09
@@ -1365,38 +1365,8 @@
 %0A%0A%09%09
-//int length = xpath.length();
 %0A%09%09i
@@ -1803,30 +1803,640 @@
 %0A%0A%09%09
-%0A%09%09String%5B%5D splitted =
+String xpath2 = xpath.substring(currentPos);%0A%09%09%0A%09%09List%3CString%3E parts = new ArrayList%3C%3E(); %0A%09%09%0A%09%09int idx1 = 0;%0A%09%09int idx2 = xpath2.indexOf(stepDelimiter, idx1);%0A%09%09int length = xpath2.length();%0A%09%09int idx3, idx4;%0A%09%09String previous;%0A%09%09%0A%09%09while (idx2 != -1) %7B%0A%09%09%09previous = xpath2.substring(idx1, idx2);%0A%09%09%09idx3 = previous.lastIndexOf(%22%5B%22);%0A%09%09%09idx4 = previous.lastIndexOf(%22%5D%22);%0A%09%09%09if (idx3 == -1 %7C%7C idx4 %3E idx3) %7B%0A%09%09%09%09parts.add(previous);%0A%09%09%09%09idx1 = idx2;%0A%09%09%09%7D%0A%09%09%09%0A%09%09%09idx2 = xpath2.indexOf(stepDelimiter, idx2 + 1);%0A%09%09%7D%0A%09%09previous = xpath2.substring(idx1);%0A%09%09parts.add(previous);%0A%09%09%0A%09%09String%5B%5D splitted = parts.toArray(new String%5B0%5D); //
  xpa

fix splitting