/*
 * Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */

package me.lucko.luckperms.common.utils;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import com.google.common.collect.ImmutableList;

import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Message;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

public class DebugHandler {
    private final String pluginVersion;

    @Setter
    private boolean pasted = false;

    @Setter
    private List<String> pastedFilters = ImmutableList.of();

    private final List<String> pastedList = Collections.synchronizedList(new ArrayList<>());

    private final Map<Receiver, List<String>> listeners;
    private final Queue<Data> queue;

    public DebugHandler(Executor executor, String pluginVersion) {
        this.pluginVersion = "v" + pluginVersion;
        listeners = new ConcurrentHashMap<>();
        queue = new ConcurrentLinkedQueue<>();

        executor.execute(() -> {
            while (true) {
                for (Data e; (e = queue.poll()) != null; ) {
                    handleOutput(e.getChecked(), e.getNode(), e.getValue());
                }

                try {
                    Thread.sleep(200);
                } catch (InterruptedException ignored) {
                }
            }
        });
    }

    private void handleOutput(String checked, String node, Tristate value) {
        if (pasted) {
            for (String filter : pastedFilters) {
                if (node.toLowerCase().startsWith(filter.toLowerCase())) continue;
                if (checked.equalsIgnoreCase(filter)) continue;
                break;
            }
            
            pastedList.add("`" + checked + "` - " + node + " - **" + value.toString() + "**   ");
        }

        all:
        for (Map.Entry<Receiver, List<String>> e : listeners.entrySet()) {
            for (String filter : e.getValue()) {
                if (node.toLowerCase().startsWith(filter.toLowerCase())) continue;
                if (checked.equalsIgnoreCase(filter)) continue;
                continue all;
            }

            Message.LOG.send(e.getKey().getSender(), "&7Checking &a" + checked + "&7 for: &a" + node + " &f(&7" + value.toString() + "&f)");
        }
    }

    public void offer(String checked, String node, Tristate value) {
        queue.offer(new Data(checked, node, value));
    }

    public void register(Sender sender, List<String> filters) {
        listeners.put(new Receiver(sender.getUuid(), sender), ImmutableList.copyOf(filters));
    }

    public void unregister(UUID uuid) {
        listeners.remove(new Receiver(uuid, null));
    }

    public String uploadPastedData() {
        List<String> output = ImmutableList.<String>builder()
                .add("#### This file was automatically generated by [LuckPerms](https://github.com/lucko/LuckPerms) " + pluginVersion)
                .add("")
                .add("Format: `<checked>` `<permission>` `<value>`")
                .add("")
                .add("___")
                .add("")
                .addAll(pastedList)
                .build();

        pastedList.clear();
        return PasteUtils.paste(output.stream().collect(Collectors.joining("\n")));
    }

    @Getter
    @EqualsAndHashCode(of = "uuid")
    @AllArgsConstructor
    private static final class Receiver {
        private final UUID uuid;
        private final Sender sender;
    }

    @Getter
    @AllArgsConstructor
    private static final class Data {
        private final String checked;
        private final String node;
        private final Tristate value;
    }
}

@@ -2745,33 +2745,16 @@
 nored) %7B
-%0A                
 %7D%0A      
@@ -2849,32 +2849,47 @@
 istate value) %7B%0A
+        paste:%0A
         if (past
@@ -3112,16 +3112,22 @@
    break
+ paste
 ;%0A      

Fix verbose recording filters (again)