/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.netbeans.modules.css.prep.editor;

import java.io.IOException;
import org.netbeans.modules.css.prep.editor.model.CPModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.modules.csl.api.ColoringAttributes;
import org.netbeans.modules.csl.api.CompletionProposal;
import org.netbeans.modules.csl.api.DeclarationFinder;
import org.netbeans.modules.csl.api.DeclarationFinder.DeclarationLocation;
import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.HtmlFormatter;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.api.StructureItem;
import org.netbeans.modules.css.editor.module.spi.CompletionContext;
import org.netbeans.modules.css.editor.module.spi.CssEditorModule;
import org.netbeans.modules.css.editor.module.spi.EditorFeatureContext;
import org.netbeans.modules.css.editor.module.spi.FeatureContext;
import org.netbeans.modules.css.editor.module.spi.FutureParamTask;
import org.netbeans.modules.css.editor.module.spi.SemanticAnalyzer;
import org.netbeans.modules.css.editor.module.spi.Utilities;
import org.netbeans.modules.css.lib.api.CssParserResult;
import org.netbeans.modules.css.lib.api.CssTokenId;
import org.netbeans.modules.css.lib.api.Node;
import org.netbeans.modules.css.lib.api.NodeType;
import org.netbeans.modules.css.lib.api.NodeUtil;
import org.netbeans.modules.css.lib.api.NodeVisitor;
import org.netbeans.modules.css.prep.editor.model.CPElement;
import org.netbeans.modules.css.prep.editor.model.CPElementHandle;
import org.netbeans.modules.css.prep.editor.model.CPElementType;
import org.netbeans.modules.parsing.api.ParserManager;
import org.netbeans.modules.parsing.api.ResultIterator;
import org.netbeans.modules.parsing.api.Snapshot;
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.api.UserTask;
import org.netbeans.modules.parsing.spi.ParseException;
import org.netbeans.modules.parsing.spi.Parser;
import org.netbeans.modules.web.common.api.DependencyType;
import org.netbeans.modules.web.common.api.LexerUtils;
import org.netbeans.modules.web.common.api.Lines;
import org.netbeans.modules.web.common.api.WebUtils;
import org.netbeans.modules.web.common.spi.ProjectWebRootQuery;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Pair;
import org.openide.util.lookup.ServiceProvider;

/**
 * CSS preprocessor {@link CssEditorModule} implementation.
 *
 * TODO fix the instant rename and the mark occurrences - they are pretty naive
 * - not scoped at all :-)
 *
 * @author marekfukala
 */
@ServiceProvider(service = CssEditorModule.class)
public class CPCssEditorModule extends CssEditorModule {

    private final SemanticAnalyzer semanticAnalyzer = new CPSemanticAnalyzer();
    private static Map<NodeType, ColoringAttributes> COLORINGS;
    private static final Collection<String> PSEUDO_CLASSES = Arrays.asList(new String[]{
                "extend" //NOI18N
            });

    @Override
    public SemanticAnalyzer getSemanticAnalyzer() {
        return semanticAnalyzer;
    }

    @Override
    @SuppressWarnings("fallthrough")
    public List<CompletionProposal> getCompletionProposals(final CompletionContext context) {
        final List<CompletionProposal> proposals = new ArrayList<>();

        CPModel model = CPModel.getModel(context.getParserResult());
        if (model == null) {
            return Collections.emptyList();
        }
        List<CompletionProposal> allVars = new ArrayList<>(getVariableCompletionProposals(context, model));

        //errorneous source
        TokenSequence<CssTokenId> ts = context.getTokenSequence();
        Token<CssTokenId> token = ts.token();
        if (token == null) {
            return Collections.emptyList();
        }
        CssTokenId tid = token.id();
        CharSequence ttext = token.text();
        char first = ttext.charAt(0);

        switch (tid) {
            case ERROR:
                switch (first) {
                case '$':
                    //"$" as a prefix - user likely wants to type variable
                    //check context
                    if (NodeUtil.getAncestorByType(context.getActiveTokenNode(), NodeType.rule) != null
                            || NodeUtil.getAncestorByType(context.getActiveTokenNode(), NodeType.cp_mixin_block) != null) {
                    //in declarations node -> offer all vars
                    return Utilities.filterCompletionProposals(allVars, context.getPrefix(), true);
                }
                    break;
            }
            case AT_SIGN:
                switch (first) {
                case '@':
                    //may be:
                    //1. @-rule beginning
                    //2. less variable

                    //1.@-rule
                    proposals.addAll(Utilities.createRAWCompletionProposals(model.getDirectives(), ElementKind.KEYWORD, context.getAnchorOffset()));

                    //2.less variables
                    if (model.getPreprocessorType() == CPType.LESS) {
                        proposals.addAll(allVars);
                    }
                    return Utilities.filterCompletionProposals(proposals, context.getPrefix(), true);
            }
                break;

            case SASS_VAR:
                //sass variable: $v|
                if (model.getPreprocessorType() == CPType.SCSS) {
                return Utilities.filterCompletionProposals(allVars, context.getPrefix(), true);
            }

            case AT_IDENT:
                //not complete keyword (complete keyword have their own token types,
                //but no need to complete them except documentation completion request
                List<CompletionProposal> props = Utilities.createRAWCompletionProposals(model.getDirectives(), ElementKind.KEYWORD, context.getAnchorOffset());

                //less variable: @va|
                if (model.getPreprocessorType() == CPType.LESS) {
                    return Utilities.filterCompletionProposals(allVars, context.getPrefix(), true);
                }
                return Utilities.filterCompletionProposals(props, context.getPrefix(), true);
        }

        Node activeNode = context.getActiveNode();
        boolean isError = false;
        //skip to first non error or recovery parent
        while (activeNode.type() == NodeType.error || activeNode.type() == NodeType.recovery) {
            isError = true;
            activeNode = activeNode.parent();
        }
//        NodeUtil.dumpTree(context.getParseTreeRoot());

        switch (activeNode.type()) {
            case bodyItem:
            case mediaBody:
            case mediaBodyItem:
            case cssClass:
                switch (tid) {
                case WS:
                    //in stylesheet main body: @include |
                    //check the previous token
                    if (ts.movePrevious()) {
                    Token<CssTokenId> previousToken = ts.token();
                    if (previousToken.id() == CssTokenId.SASS_INCLUDE) {
                        //add all mixins
                        proposals.addAll(getMixinsCompletionProposals(context, model));
                    }
                }
                    break;

                case IDENT:
                    if (LexerUtils.followsToken(ts, CssTokenId.SASS_INCLUDE, true, true, CssTokenId.WS) != null) {
                        //in stylesheet main body: @include mix|
                        //ok so the ident if preceeded by WS and then by SASS_INCLUDE token
                        proposals.addAll(getMixinsCompletionProposals(context, model));
                    } else if (LexerUtils.followsToken(ts, CssTokenId.DOT, true, true, CssTokenId.WS) != null) {
                        //in stylesheet main body: .mix| --> less mixins
                        proposals.addAll(getMixinsCompletionProposals(context, model));
                    }
                    break;
                case DOT:
                    proposals.addAll(getMixinsCompletionProposals(context, model));
                break;
            }
                break;
            case cp_mixin_call:
            //@include |
            case cp_mixin_name:
                //@include mymi|
                proposals.addAll(getMixinsCompletionProposals(context, model));
                break;

            case cp_variable:
                //already in the prefix
                proposals.addAll(allVars);
                break;
            case propertyValue:
                //just $ or @ prefix
                if (context.getPrefix().length() == 1 && context.getPrefix().charAt(0) == model.getPreprocessorType().getVarPrefix()) {
                proposals.addAll(allVars);
            }
                break;
            case declaration:
                switch (tid) {
                case DOT:
                    //div { .| } -- less mixin call
                    proposals.addAll(getMixinsCompletionProposals(context, model));
                    break;
                case WS:
                    //go back and find first non white token
                    while (ts.movePrevious()
                            && (ts.token().id() == CssTokenId.WS
                            || ts.token().id() == CssTokenId.NL)) {
                    //skip ws backward
                }
                    switch (ts.token().id()) {
                        case SASS_INCLUDE:
                            //completion at: @include |
                            proposals.addAll(getMixinsCompletionProposals(context, model));
                            break;

                    }

            }
                break;
            case selectorsGroup:
                switch (ts.token().id()) {
                    case DOT:
                        //.| in body => less mixins
                        proposals.addAll(getMixinsCompletionProposals(context, model));
                }
                break;

        }
        return Utilities.filterCompletionProposals(proposals, context.getPrefix(), true);
    }

    private static Collection<CompletionProposal> getVariableCompletionProposals(final CompletionContext context, CPModel model) {
        //filter the variable at the current location (being typed)
        Collection<CompletionProposal> proposals = new LinkedHashSet<>();
        for (CPElement var : model.getVariables(context.getCaretOffset())) {
            if (var.getType() != CPElementType.VARIABLE_USAGE && !var.getRange().containsInclusive(context.getCaretOffset())) {
                ElementHandle handle = new CPCslElementHandle(context.getFileObject(), var.getName());
                VariableCompletionItem item = new VariableCompletionItem(
                        handle,
                        var.getHandle(),
                        context.getAnchorOffset(),
                        null); //no origin for current file
//                        var.getFile() == null ? null : var.getFile().getNameExt());

                proposals.add(item);
            }
        }
        try {
            //now gather global vars from all linked sheets
            FileObject file = context.getFileObject();
            if (file != null) {
                Map<FileObject, CPCssIndexModel> indexModels = CPUtils.getIndexModels(file, DependencyType.REFERRING_AND_REFERRED, true);
                for (Entry<FileObject, CPCssIndexModel> entry : indexModels.entrySet()) {
                    FileObject reff = entry.getKey();
                    CPCssIndexModel cpIndexModel = entry.getValue();
                    Collection<org.netbeans.modules.css.prep.editor.model.CPElementHandle> variables = cpIndexModel.getVariables();
                    for (org.netbeans.modules.css.prep.editor.model.CPElementHandle var : variables) {
                        if (var.getType() == CPElementType.VARIABLE_GLOBAL_DECLARATION) {
                            ElementHandle handle = new CPCslElementHandle(context.getFileObject(), var.getName());
                            VariableCompletionItem item = new VariableCompletionItem(
                                    handle,
                                    var,
                                    context.getAnchorOffset(),
                                    reff.getNameExt());

                            proposals.add(item);
                        }

                    }

                }
            }
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }

        return proposals;
    }

    private static Collection<CompletionProposal> getMixinsCompletionProposals(final CompletionContext context, CPModel model) {
        //filter the variable at the current location (being typed)
        Collection<CompletionProposal> proposals = new LinkedHashSet<>();
        for (CPElement mixin : model.getMixins()) {
            if (mixin.getType() == CPElementType.MIXIN_DECLARATION) {
                ElementHandle handle = new CPCslElementHandle(context.getFileObject(), mixin.getName());
                MixinCompletionItem item = new MixinCompletionItem(
                        handle,
                        mixin.getHandle(),
                        context.getAnchorOffset(),
                        null); //no origin for current file
//                        var.getFile() == null ? null : var.getFile().getNameExt());

                proposals.add(item);
            }
        }
        try {
            //now gather global vars from all linked sheets
            FileObject file = context.getFileObject();
            if (file != null) {
                Map<FileObject, CPCssIndexModel> indexModels = CPUtils.getIndexModels(file, DependencyType.REFERRING_AND_REFERRED, true);
                for (Entry<FileObject, CPCssIndexModel> entry : indexModels.entrySet()) {
                    FileObject reff = entry.getKey();
                    CPCssIndexModel cpIndexModel = entry.getValue();
                    Collection<org.netbeans.modules.css.prep.editor.model.CPElementHandle> mixins = cpIndexModel.getMixins();
                    for (org.netbeans.modules.css.prep.editor.model.CPElementHandle mixin : mixins) {
                        if (mixin.getType() == CPElementType.MIXIN_DECLARATION) {
                            ElementHandle handle = new CPCslElementHandle(context.getFileObject(), mixin.getName());
                            MixinCompletionItem item = new MixinCompletionItem(
                                    handle,
                                    mixin,
                                    context.getAnchorOffset(),
                                    reff.getNameExt());

                            proposals.add(item);
                        }

                    }

                }
            }
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }

        return proposals;
    }

    @Override
    public <T extends Map<OffsetRange, Set<ColoringAttributes>>> NodeVisitor<T> getSemanticHighlightingNodeVisitor(FeatureContext context, T result) {
        final Snapshot snapshot = context.getSnapshot();
        return new NodeVisitor<T>(result) {
            @Override
            public boolean visit(Node node) {
                ColoringAttributes coloring = getColorings().get(node.type());
                if (coloring != null) {
                    int dso = snapshot.getOriginalOffset(node.from());
                    int deo = snapshot.getOriginalOffset(node.to());
                    if (dso >= 0 && deo >= 0) { //filter virtual nodes
                        //check vendor speficic property
                        OffsetRange range = new OffsetRange(dso, deo);
                        getResult().put(range, Collections.singleton(coloring));
                    }
                }
                return false;
            }
        };
    }

    private static Map<NodeType, ColoringAttributes> getColorings() {
        if (COLORINGS == null) {
            COLORINGS = new EnumMap<>(NodeType.class);
            COLORINGS.put(NodeType.cp_variable, ColoringAttributes.LOCAL_VARIABLE);
            COLORINGS.put(NodeType.cp_mixin_name, ColoringAttributes.PRIVATE);
        }
        return COLORINGS;
    }

    @Override
    public <T extends Set<OffsetRange>> NodeVisitor<T> getMarkOccurrencesNodeVisitor(EditorFeatureContext context, T result) {
        return Utilities.createMarkOccurrencesNodeVisitor(context, result, NodeType.cp_variable, NodeType.cp_mixin_name);
    }

    @Override
    public boolean isInstantRenameAllowed(EditorFeatureContext context) {
        TokenSequence<CssTokenId> tokenSequence = context.getTokenSequence();
        int diff = tokenSequence.move(context.getCaretOffset());
        if (diff > 0 && tokenSequence.moveNext() || diff == 0 && tokenSequence.movePrevious()) {
            Token<CssTokenId> token = tokenSequence.token();
            return token.id() == CssTokenId.AT_IDENT //less
                    || token.id() == CssTokenId.SASS_VAR //sass
                    || token.id() == CssTokenId.IDENT; //sass/less mixin name

        }
        return false;
    }

    @Override
    public <T extends Set<OffsetRange>> NodeVisitor<T> getInstantRenamerVisitor(EditorFeatureContext context, T result) {
        TokenSequence<CssTokenId> tokenSequence = context.getTokenSequence();
        int diff = tokenSequence.move(context.getCaretOffset());
        if (diff > 0 && tokenSequence.moveNext() || diff == 0 && tokenSequence.movePrevious()) {
            Token<CssTokenId> token = tokenSequence.token();
            final CharSequence elementName = token.text();
            return new NodeVisitor<T>(result) {
                @Override
                public boolean visit(Node node) {
                    switch (node.type()) {
                        case cp_mixin_name:
                        case cp_variable:
                            if (LexerUtils.equals(elementName, node.image(), false, false)) {
                            OffsetRange range = new OffsetRange(node.from(), node.to());
                            getResult().add(range);
                            break;
                        }
                    }
                    return false;
                }
            };

        }
        return null;
    }

    @Override
    public Pair<OffsetRange, FutureParamTask<DeclarationLocation, EditorFeatureContext>> getDeclaration(Document document, int caretOffset) {
        //first try to find the reference span
        TokenSequence<CssTokenId> ts = LexerUtils.getJoinedTokenSequence(document, caretOffset, CssTokenId.language());
        if (ts == null) {
            return null;
        }

        OffsetRange foundRange = null;
        Token<CssTokenId> token = ts.token();
        int quotesDiff = WebUtils.isValueQuoted(ts.token().text().toString()) ? 1 : 0;
        OffsetRange range = new OffsetRange(ts.offset() + quotesDiff, ts.offset() + ts.token().length() - quotesDiff);
        CharSequence mixinName;

        //MIXINs go to declaration
        switch (token.id()) {
            case IDENT:
                mixinName = token.text();

                //check if there is @import token before
                while (ts.movePrevious() && ts.token().id() == CssTokenId.WS) {
                }

                Token t = ts.token();
                if (t != null) {
                    if (t.id() == CssTokenId.DOT || t.id() == CssTokenId.SASS_INCLUDE) {
                        //gotcha!
                        //@import xxx --sass
                        //.xxx --less
                        foundRange = range;
                    }
                }
                if (foundRange == null) {
                    return null;
                }

                final CharSequence searchedMixinName = mixinName;
                FutureParamTask<DeclarationLocation, EditorFeatureContext> callable = new FutureParamTask<DeclarationLocation, EditorFeatureContext>() {
                    @Override
                    public DeclarationLocation run(EditorFeatureContext context) {
                        final Collection<Pair<CPCslElementHandle, Snapshot>> locations = new ArrayList<>();
                        //first look at the current file
                        CPModel model = CPModel.getModel(context.getParserResult());
                        for (CPElement mixin : model.getMixins()) {
                            if (mixin.getType() == CPElementType.MIXIN_DECLARATION) {
                                if (LexerUtils.equals(searchedMixinName, mixin.getName(), false, false)) {
                                    locations.add(
                                            Pair.of(new CPCslElementHandle(
                                            context.getFileObject(), mixin.getName(), mixin.getRange(), mixin.getType()),
                                            context.getSnapshot()));
                                }
                            }
                        }

                        //then look at the referred files
                        try {
                            Map<FileObject, CPCssIndexModel> indexModels = CPUtils.getIndexModels(context.getFileObject(), DependencyType.REFERRING_AND_REFERRED, true);
                            for (Entry<FileObject, CPCssIndexModel> entry : indexModels.entrySet()) {
                                final CPCssIndexModel im = entry.getValue();
                                final FileObject file = entry.getKey();
                                Source source = Source.create(file);
                                ParserManager.parse(Collections.singleton(source), new UserTask() {
                                    @Override
                                    public void run(ResultIterator resultIterator) throws Exception {
                                        ResultIterator cssRI = WebUtils.getResultIterator(resultIterator, "text/css");
                                        if (cssRI != null) {
                                            Parser.Result parserResult = cssRI.getParserResult();
                                            if (parserResult instanceof CssParserResult) {
                                                CssParserResult result = (CssParserResult) parserResult;
                                                CPModel model = CPModel.getModel(result);
                                                for (CPElementHandle mixin : im.getMixins()) {
                                                    if (mixin.getType() == CPElementType.MIXIN_DECLARATION
                                                            && LexerUtils.equals(searchedMixinName, mixin.getName(), false, false)) {
                                                        CPElement element = mixin.resolve(model);
                                                        if (element != null) {
                                                            locations.add(Pair.of(new CPCslElementHandle(
                                                                    file, mixin.getName(), element.getRange(), mixin.getType()),
                                                                    result.getSnapshot()));
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                });
                            }
                        } catch (ParseException | IOException ex) {
                            Exceptions.printStackTrace(ex);
                        }

                        if (locations.isEmpty()) {
                            return DeclarationLocation.NONE;
                        } else {
                            Iterator<Pair<CPCslElementHandle, Snapshot>> itr = locations.iterator();
                            DeclarationLocation main = null;

                            while (itr.hasNext()) {
                                Pair<CPCslElementHandle, Snapshot> item = itr.next();
                                CPCslElementHandle handle = item.first();
                                Snapshot snapshot = item.second();
                                Lines lines = new Lines(snapshot.getText());
                                DeclarationLocation location = new DeclarationLocation(
                                        handle.getFileObject(), handle.getOffsetRange(null).getStart());
                                if (main == null) {
                                    main = location;
                                }
                                DeclarationFinder.AlternativeLocation alternative
                                        = new CpAlternativeLocation(handle, location, snapshot, lines, handle.getFileObject().equals(context.getSource().getFileObject()));
                                main.addAlternative(alternative);
                            }
                            return main;
                        }

                    }
                };
                return Pair.<OffsetRange, FutureParamTask<DeclarationLocation, EditorFeatureContext>>of(foundRange, callable);

            case SASS_VAR:
            case AT_IDENT: //less var //TODO - add default directives - see the css grammar file comment about that
                //cp variable
                final String varName = token.text().toString();
                foundRange = new OffsetRange(ts.offset(), ts.offset() + ts.token().length());

                callable = new FutureParamTask<DeclarationLocation, EditorFeatureContext>() {
                    @Override
                    public DeclarationLocation run(EditorFeatureContext context) {
                        final Collection<Pair<CPCslElementHandle, Snapshot>> locations = new ArrayList<>();
                        //first look at the current file
                        CPModel model = CPModel.getModel(context.getParserResult());
                        for (CPElement var : model.getVariables()) {
                            if (var.getType().isOfTypes(CPElementType.VARIABLE_GLOBAL_DECLARATION, CPElementType.VARIABLE_LOCAL_DECLARATION, CPElementType.VARIABLE_DECLARATION_IN_BLOCK_CONTROL)) {
                                if (LexerUtils.equals(varName, var.getName(), false, false)) {
                                    locations.add(
                                            Pair.of(
                                            new CPCslElementHandle(
                                            context.getFileObject(),
                                            var.getName(),
                                            var.getRange(),
                                            var.getType()),
                                            context.getSnapshot()));
                                }
                            }
                        }
                        try {
                            //then look at the referred files
                            Map<FileObject, CPCssIndexModel> indexModels = CPUtils.getIndexModels(context.getFileObject(), DependencyType.REFERRING_AND_REFERRED, true);
                            for (Entry<FileObject, CPCssIndexModel> entry : indexModels.entrySet()) {
                                final CPCssIndexModel im = entry.getValue();
                                final FileObject file = entry.getKey();
                                Source source = Source.create(file);
                                ParserManager.parse(Collections.singleton(source), new UserTask() {
                                    @Override
                                    public void run(ResultIterator resultIterator) throws Exception {
                                        ResultIterator cssRI = WebUtils.getResultIterator(resultIterator, "text/css");
                                        if (cssRI != null) {
                                            CssParserResult result = (CssParserResult) cssRI.getParserResult();
                                            CPModel model = CPModel.getModel(result);
                                            for (CPElementHandle var : im.getVariables()) {
                                                if (var.getType() == CPElementType.VARIABLE_GLOBAL_DECLARATION && var.getName().equals(varName)) {
                                                    CPElement element = var.resolve(CPModel.getModel(file));
                                                    if (element != null) {
                                                        locations.add(
                                                                Pair.of(
                                                                new CPCslElementHandle(
                                                                file,
                                                                var.getName(),
                                                                element.getRange(),
                                                                var.getType()),
                                                                result.getSnapshot()
                                                                ));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                });
                            }
                        } catch (ParseException | IOException ex) {
                            Exceptions.printStackTrace(ex);
                        }

                        if (locations.isEmpty()) {
                            return DeclarationLocation.NONE;
                        } else {
                            Iterator<Pair<CPCslElementHandle, Snapshot>> itr = locations.iterator();
                            DeclarationLocation main = null;

                            while (itr.hasNext()) {
                                Pair<CPCslElementHandle, Snapshot> item = itr.next();
                                CPCslElementHandle handle = item.first();
                                Snapshot snapshot = item.second();
                                Lines lines = new Lines(snapshot.getText());
                                DeclarationLocation location = new DeclarationLocation(
                                        handle.getFileObject(), handle.getOffsetRange(null).getStart());
                                if (main == null) {
                                    main = location;
                                }
                                DeclarationFinder.AlternativeLocation alternative
                                        = new CpAlternativeLocation(handle, location, snapshot, lines, handle.getFileObject().equals(context.getSource().getFileObject()));
                                main.addAlternative(alternative);
                            }
                            return main;
                        }
                    }
                };
                return Pair.<OffsetRange, FutureParamTask<DeclarationLocation, EditorFeatureContext>>of(foundRange, callable);

            default:
                return null;
        }

    }

    @Override
    public <T extends Map<String, List<OffsetRange>>> NodeVisitor<T> getFoldsNodeVisitor(FeatureContext context, T result) {
        final Snapshot snapshot = context.getSnapshot();
        final Lines lines = new Lines(snapshot.getText());

        return new NodeVisitor<T>(result) {
            @Override
            public boolean visit(Node node) {
                switch (node.type()) {
                    case sass_control_block:
                    case cp_mixin_block:
                    case sass_map:
                    case sass_function_declaration:
                        //find the ruleSet curly brackets and create the fold between them inclusive
                        int from = node.from();
                        int to = node.to();
                        try {
                            //do not creare one line folds
                            if (lines.getLineIndex(from) < lines.getLineIndex(to)) {
                                List<OffsetRange> codeblocks = getResult().get("codeblocks"); //NOI18N
                                if (codeblocks == null) {
                                    codeblocks = new ArrayList<>();
                                    getResult().put("codeblocks", codeblocks); //NOI18N
                                }

                                codeblocks.add(new OffsetRange(from, to));
                            }
                        } catch (BadLocationException ex) {
                            Exceptions.printStackTrace(ex);
                        }
                }
                return false;
            }
        };

    }

    @Override
    public <T extends List<StructureItem>> NodeVisitor<T> getStructureItemsNodeVisitor(FeatureContext context, T result) {

        final Set<StructureItem> vars = new HashSet<>();
        final Set<StructureItem> mixins = new HashSet<>();

        CPModel model = CPModel.getModel(context.getParserResult());
        for (CPElement element : model.getElements()) {
            switch (element.getType()) {
                case MIXIN_DECLARATION:
                    mixins.add(new CPStructureItem.Mixin(element));
                    break;
//                case VARIABLE_DECLARATION_IN_BLOCK_CONTROL:
                case VARIABLE_GLOBAL_DECLARATION:
//                case VARIABLE_LOCAL_DECLARATION:
                    vars.add(new CPStructureItem.Variable(element));
                    break;
            }
        }

        if (!vars.isEmpty()) {
            result.add(new CPCategoryStructureItem.Variables(vars));
        }
        if (!mixins.isEmpty()) {
            result.add(new CPCategoryStructureItem.Mixins(mixins, context));
        }

        //XXX ugly - we need no visitor, but still forced to return one
        return new NodeVisitor<T>() {
            @Override
            public boolean visit(Node node) {
                return true;
            }
        };

    }

    @Override
    public Collection<String> getPseudoClasses(EditorFeatureContext context) {
        Collection<String> result = null;
        if (CPUtils.LESS_FILE_MIMETYPE.equals(context.getSource().getMimeType())) {
            result = PSEUDO_CLASSES;
        }
        return result;
    }

    private static class CpAlternativeLocation implements DeclarationFinder.AlternativeLocation {

        private static final int TEXT_MAX_LENGTH = 50;

        private final CPCslElementHandle handle;
        private final DeclarationLocation location;
        private int lineIndex = -1;
        private String lineText;
        private final boolean currentFile;

        public CpAlternativeLocation(CPCslElementHandle handle, DeclarationLocation location, Snapshot snapshot, Lines lines, boolean currentFile) {
            this.handle = handle;
            this.location = location;
            this.currentFile = currentFile;
            try {
                lineIndex = lines.getLineIndex(location.getOffset());
                //line bounds
                int from = lines.getLineOffset(lineIndex);
                int to = lines.getLinesCount() > (lineIndex + 1)
                        ? lines.getLineOffset(lineIndex + 1)
                        : snapshot.getText().length();
                lineText = snapshot.getText().subSequence(from, to).toString();
            } catch (BadLocationException ex) {
                Logger.getLogger(CpAlternativeLocation.class.getName()).log(Level.INFO, null, ex);
            }
        }

        @Override
        public ElementHandle getElement() {
            return handle;
        }

        @Override
        public String getDisplayHtml(HtmlFormatter b) {
            //line text section
            if (lineText != null) {
                //split the text to three parts: the element text itself, its prefix and postfix
                //then render the element test in bold
                String elementText = handle.getName();

                String prefix = "";
                String postfix = "";
                //strip the line to the body start
                int elementIndex = lineText.indexOf(elementText);
                if (elementIndex >= 0) {
                    //find the closest opening curly bracket or NL forward
                    int to;
                    for (to = elementIndex; to < lineText.length(); to++) {
                        char c = lineText.charAt(to);
                        if (c == '{' || c == '\n') {
                            break;
                        }
                    }
                    //now find nearest closing curly bracket or newline backward
                    int from;
                    for (from = elementIndex; from >= 0; from--) {
                        char ch = lineText.charAt(from);
                        if (ch == '}' || ch == '\n') {
                            break;
                        }
                    }

                    prefix = lineText.substring(from + 1, elementIndex).trim();
                    postfix = lineText.substring(elementIndex + elementText.length(), to).trim();

                    //now strip the prefix and postfix so the whole text is not longer than SELECTOR_TEXT_MAX_LENGTH
                    int overlap = (prefix.length() + elementText.length() + postfix.length()) - TEXT_MAX_LENGTH;
                    if (overlap > 0) {
                        //strip
                        int stripFromPrefix = Math.min(overlap / 2, prefix.length());
                        prefix = ".." + prefix.substring(stripFromPrefix);
                        int stripFromPostfix = Math.min(overlap - stripFromPrefix, postfix.length());
                        postfix = postfix.substring(0, postfix.length() - stripFromPostfix) + "..";
                    }
                }

                b.appendHtml("<span>");//NOI18N
                b.appendText(prefix);
                b.appendText(" "); //NOI18N
                b.appendHtml("<b>"); //NOI18N
                b.appendText(elementText);
                b.appendHtml("</b>"); //NOI18N
                b.appendText(" "); //NOI18N
                b.appendText(postfix);
                b.appendHtml("</span>"); //NOI18N
            }

            //file:offset section
            b.appendHtml("<span>");
            if (!isLocalDeclaration()) {
                //add a link to the file relative to the web root
                FileObject file = location.getFileObject();
                FileObject pathRoot = ProjectWebRootQuery.getWebRoot(file);

                String path = null;
                String resolveTo = null;
                if (pathRoot != null) {
                    path = FileUtil.getRelativePath(pathRoot, file); //this may also return null
                }
                if (path == null) {
                    //the file cannot be resolved relatively to the webroot or no webroot found
                    //try to resolve relative path to the project's root folder
                    Project project = FileOwnerQuery.getOwner(file);
                    if (project != null) {
                        pathRoot = project.getProjectDirectory();
                        path = FileUtil.getRelativePath(pathRoot, file); //this may also return null
                        if (path != null) {
                            resolveTo = "${project.home}/"; //NOI18N
                        }
                    }
                }

                if (path == null) {
                    //if everything fails, just use the absolute path
                    path = file.getPath();
                }
                b.appendText(" in ");
                if (resolveTo != null) {
                    b.appendHtml("<i>"); //NOI18N
                    b.appendText(resolveTo);
                    b.appendHtml("</i>"); //NOI18N
                }
                b.appendText(path);
                if (lineIndex != -1) {
                    b.appendText(":"); //NOI18N
                    b.appendText(Integer.toString(lineIndex + 1)); //line offsets are counted from zero, but in editor lines starts with one.
                }

            } else {
                b.appendText(" at line ");
                b.appendText(Integer.toString((lineIndex + 1)));
            }
            b.appendHtml("</span>");

            return b.getText();
        }

        @Override
        public DeclarationLocation getLocation() {
            return location;
        }

        @Override
        public int compareTo(DeclarationFinder.AlternativeLocation o) {
            CpAlternativeLocation cpal = (CpAlternativeLocation) o;

            if (isLocalDeclaration() == cpal.isLocalDeclaration()) {
                return location.getFileObject().getPath().compareTo(o.getLocation().getFileObject().getPath());
            } else {
                return isLocalDeclaration() && !cpal.isLocalDeclaration() ? -1 : +1;
            }
        }

        /**
         * Is the declaration location in the current file?
         */
        private boolean isLocalDeclaration() {
            return currentFile;
        }
    }

}
