/**
 * Copyright 2010 JBoss Inc
 *
 * 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 org.drools.eclipse.dsl.editor.completion;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;

import org.drools.eclipse.DroolsEclipsePlugin;
import org.drools.eclipse.DroolsPluginImages;
import org.drools.eclipse.dsl.editor.DSLAdapter;
import org.drools.eclipse.dsl.editor.DSLRuleEditor;
import org.drools.eclipse.editors.AbstractRuleEditor;
import org.drools.eclipse.editors.completion.RuleCompletionProcessor;
import org.drools.eclipse.editors.completion.RuleCompletionProposal;
import org.drools.lang.Location;
import org.eclipse.swt.graphics.Image;

/**
 * For handling DSL rules.
 * 
 * @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
 */
public class DSLRuleCompletionProcessor extends RuleCompletionProcessor {

	private static final Image DSL_ICON = 
		DroolsPluginImages.getImage(DroolsPluginImages.DSL_EXPRESSION);

	public DSLRuleCompletionProcessor(AbstractRuleEditor editor) {
		super(editor);
	}

    protected DSLRuleEditor getDSLRuleEditor() {
    	return (DSLRuleEditor) getEditor();
    }
    
	protected void addRHSCompletionProposals(List list, int documentOffset, String prefix, String backText,
			String conditions, String consequence) {
		// super.addRHSCompletionProposals(list, documentOffset, prefix, backText, conditions, consequence);
		DSLAdapter adapter = getDSLRuleEditor().getDSLAdapter();
		if (adapter != null) {
			List dslConsequences = adapter.getDSLTree().getConsequenceChildrenList(prefix, true);
			addDSLProposals(list, documentOffset, prefix, dslConsequences);
		}
	}
	
	protected void addLHSCompletionProposals(List list, int documentOffset,
			Location location, String prefix, String backText) {
		// super.addLHSCompletionProposals(list, documentOffset, location, prefix, backText);
		DSLAdapter adapter = getDSLRuleEditor().getDSLAdapter();
		if (adapter != null) {
			String lastobj = this.getLastNonDashLine(backText);
			String last = this.getLastLine(backText);
			// we have to check if the last line is when. if it is we set
			// the last line to zero length string
			boolean firstLine = false;
			if (lastobj.equals("when")) {
				firstLine = true;
				last = "";
				lastobj = "*";
			}
			last = last.trim();
			// pass the last string in the backText to getProposals
			List dslConditions = this.getProposals(adapter, lastobj, last, firstLine);
			// if we couldn't find any matches, we add the list from
			// the DSLAdapter so that there's something
//			if (dslConditions.size() == 0) {
//				dslConditions.addAll(adapter.listConditionItems());
//			}
			addDSLProposals(list, documentOffset, last, dslConditions);
		}
	}
	
	private void addDSLProposals(final List list, int documentOffset, final String prefix, List dslItems) {
		Iterator iterator = dslItems.iterator();
		while (iterator.hasNext()) {
			String consequence = (String) iterator.next();
			RuleCompletionProposal p = new RuleCompletionProposal(
				documentOffset - prefix.length(), prefix.length(), consequence);
			p.setImage(DSL_ICON);
			list.add(p);
		}
	}

	/**
	 * because of how the backText works, we need to get the last line, so that
	 * we can pass it to the DSLUtility
	 * 
	 * @param backText
	 * @return
	 */
	public String getLastLine(String backText) {
		BufferedReader breader = new BufferedReader(new StringReader(backText));
		String last = "";
		String line = null;
		try {
			while ((line = breader.readLine()) != null) {
				// only if the line has text do we set last to it
				if (line.length() > 0) {
					last = line;
				}
			}
		} catch (IOException e) {
			DroolsEclipsePlugin.log(e);
		}
		// now that all the conditions for a single object are on the same line
		// we need to check for the left parenthesis
		if (last.indexOf("(") > -1) {
			last = last.substring(last.lastIndexOf("(") + 1);
		}
		// if the string has a comma "," we get the substring starting from
		// the index after the last comma
		if (last.indexOf(",") > -1) {
			last = last.substring(last.lastIndexOf(",") + 1);
		}
		// if the line ends with right parenthesis, we change it to zero length
		// string
		if (last.endsWith(")")) {
			last = "";
		}
		return last;
	}

	/**
	 * Returns the last line that doesn't start with a dash
	 * 
	 * @param backText
	 * @return
	 */
	public String getLastNonDashLine(String backText) {
		BufferedReader breader = new BufferedReader(new StringReader(backText));
		String last = "";
		String line = null;
		try {
			while ((line = breader.readLine()) != null) {
				// there may be blank lines, so we trim first
				line = line.trim();
				// only if the line has text do we set last to it
				if (line.length() > 0 && !line.startsWith("-")) {
					last = line;
				}
			}
		} catch (IOException e) {
			DroolsEclipsePlugin.log(e);
		}
		if (last.indexOf("(") > -1 && !last.endsWith(")")) {
			last = last.substring(0, last.indexOf("("));
		} else if (last.indexOf("(") > -1 && last.endsWith(")")) {
			last = "";
		}
		return last;
	}

	/**
	 * The DSLTree is configurable. It can either return just the child of the
	 * last token found, or it can traverse the tree and generate all the
	 * combinations beneath the last matching node. TODO I don't know how to add
	 * configuration to the editor, so it needs to be hooked up to the
	 * configuration for the editor later.
	 * 
	 * @param last
	 * @return
	 */
	protected List getProposals(DSLAdapter adapter, String obj, String last, boolean firstLine) {
		if (last.length() == 0) {
			last = " ";
		}
		return adapter.getDSLTree().getChildrenList(obj, last, true, firstLine);
	}
}
