/*
 * 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.javascript2.editor.navigation;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.modules.csl.api.ColoringAttributes;
import org.netbeans.modules.csl.api.OccurrencesFinder;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.javascript2.editor.parser.JsonParserResult;
import org.netbeans.modules.javascript2.lexer.api.JsTokenId;
import org.netbeans.modules.javascript2.lexer.api.LexUtilities;
import org.netbeans.modules.javascript2.model.api.JsObject;
import org.netbeans.modules.javascript2.model.api.Model;
import org.netbeans.modules.javascript2.model.api.ModelUtils;
import org.netbeans.modules.javascript2.types.spi.ParserResult;
import org.netbeans.modules.parsing.spi.Scheduler;
import org.netbeans.modules.parsing.spi.SchedulerEvent;

/**
 *
 * @author Dusan Balek
 */
public class JsonOccurrencesFinder extends OccurrencesFinder<JsonParserResult> {

    private final AtomicBoolean cancelled = new AtomicBoolean();
    private int caretPosition;
    private Map<OffsetRange, ColoringAttributes> range2Attribs;    

    @Override
    public void setCaretPosition(int position) {
        caretPosition = position;
    }

    @Override
    public Map<OffsetRange, ColoringAttributes> getOccurrences() {
        return range2Attribs;
    }

    @Override
    public void run(JsonParserResult result, SchedulerEvent event) {
        range2Attribs = calculateOccurences(result, caretPosition, true, cancelled);
    }

    @Override
    public int getPriority() {
        return 0;
    }

    @Override
    public Class<? extends Scheduler> getSchedulerClass() {
        return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;
    }

    @Override
    public void cancel() {
        cancelled.set(true);
    }

    @NonNull
    public static Set<OffsetRange> calculateOccurances(
            @NonNull final ParserResult result,
            final int caretPosition,
            final boolean includeQuotes) {
        final Map<OffsetRange,ColoringAttributes> occ = calculateOccurences(
                result,
                caretPosition,
                includeQuotes,
                new AtomicBoolean());
        return occ == null ?
                Collections.emptySet() :
                occ.keySet();
    }

    @CheckForNull
    private static Map<OffsetRange, ColoringAttributes> calculateOccurences(
            @NonNull final ParserResult result,
            final int caretPosition,
            boolean includeQuotes,
            @NonNull final AtomicBoolean cancelled) {
        if (cancelled.getAndSet(false)) {
            return null;
        }
        TokenHierarchy<?> th = result.getSnapshot().getTokenHierarchy();
        if (th == null) {
            return null;
        }
        TokenSequence<JsTokenId> ts = th.tokenSequence(JsTokenId.jsonLanguage());
        if (ts == null) {
            return null;
        }
        int offset = result.getSnapshot().getEmbeddedOffset(caretPosition);
        int delta = ts.move(offset);
        if (!ts.moveNext() && !ts.movePrevious()){
            return null;
        }
        final Model model = Model.getModel(result, false);
        if (model == null) {
            return null;
        }
        Token<? extends JsTokenId> token = ts.token();
        JsTokenId tokenId = token.id();
        if (tokenId != JsTokenId.STRING && delta == 0 && ts.movePrevious()) {
            token = ts.token();
            tokenId = token.id();
        }
        ts.movePrevious();
        final Token<? extends JsTokenId> prevToken = LexUtilities.findPreviousNonWsNonComment(ts);
        final JsTokenId prevTokenId = prevToken.id();
        Set<OffsetRange> ranges = new HashSet<>();
        if (tokenId == JsTokenId.STRING && (prevTokenId == JsTokenId.BRACKET_LEFT_CURLY || prevTokenId == JsTokenId.OPERATOR_COMMA)) {
            CharSequence text = token.text();
            findRanges(model.getGlobalObject(), text.subSequence(1, text.length() - 1).toString(), includeQuotes, ranges);
        }
        final Map<OffsetRange, ColoringAttributes> res = new HashMap<>();
        if (cancelled.getAndSet(false)) {
            return null;
        }
        for (OffsetRange offsetRange : ranges) {
            res.put(ModelUtils.documentOffsetRange(result, offsetRange.getStart(), offsetRange.getEnd()), ColoringAttributes.MARK_OCCURRENCES);
        }
        return res;
    }

    private static void findRanges(JsObject object, String key, boolean includeQuotes, Set<OffsetRange> ranges) {
        for (Map.Entry<String, ? extends JsObject> entry : object.getProperties().entrySet()) {
            if (!entry.getValue().isAnonymous() && key.equals(entry.getKey())) {
                ranges.add(new OffsetRange(
                        (includeQuotes ? 0 : 1) + entry.getValue().getOffset(),
                        (includeQuotes ? 2 : 1) + entry.getValue().getOffset() + key.length()));
            }
            findRanges(entry.getValue(), key, includeQuotes, ranges);
        }
    }
}
