/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * 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.List;

import org.drools.compiler.lang.Location;
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.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.swt.graphics.Image;

/**
 * For handling DSL rules.
 */
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<ICompletionProposal> 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<String> dslConsequences = adapter.getDSLTree().getConsequenceChildrenList(prefix, true);
            addDSLProposals(list, documentOffset, prefix, dslConsequences);
        }
    }

    protected void addLHSCompletionProposals(List<ICompletionProposal> 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<String> 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<ICompletionProposal> list, int documentOffset, final String prefix, List<String> dslItems) {
        for (String consequence : dslItems) {
            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<String> getProposals(DSLAdapter adapter, String obj, String last, boolean firstLine) {
        if (last.length() == 0) {
            last = " ";
        }
        return adapter.getDSLTree().getChildrenList(obj, last, true, firstLine);
    }
}
