package me.koba1.led.model.colors;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.ToString;
import me.koba1.led.utils.ColorConstants;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@ToString
public class KobaOutputColor {

    @Getter private final Map<Integer, KobaColor> colors;

    public KobaOutputColor() {
        this.colors = new HashMap<>();
    }

    public KobaOutputColor(Map<Integer, KobaColor> colors) {
        this.colors = colors;
    }

    public Map<Integer, Integer> getIntegerColors() {
        Map<Integer, Integer> integerColors = new LinkedHashMap<>();
        for (Map.Entry<Integer, KobaColor> entry : colors.entrySet()) {
            integerColors.put(entry.getKey(), entry.getValue().getHexInt());
        }
        return integerColors;
    }

    public void fill(int ledCount, KobaColor color) {
        for (int i = 0; i < ledCount; i++) {
            this.colors.put(i, color);
        }
    }

    public void fill(List<KobaColor> colors) {
        int counter = 0;
        for (KobaColor color : colors) {
            this.colors.put(counter, color);
            counter++;
        }
    }

    public KobaColor set(int index, KobaColor color) {
        this.colors.put(index, color);
        return color;
    }

    public void add(KobaColor color) {
        this.colors.put(colors.size(), color);
    }

    public void set(KobaOutputColor colors) {
        this.colors.clear();
        this.colors.putAll(colors.colors);
    }

//    /**
//     * Overrides first element of map
//     * @param color
//     */
//    public void insert(String color) {
//        this.colors.put(0, color);
//    }
//
//    /**
//     * Set first element and shift other elements
//     * @param color
//     */
//    public void insertAndShift(String color) {
//        Map<Integer, String> shifted = new HashMap<>();
//
//        shifted.put(0, color);
//        for (Map.Entry<Integer, String> entry : this.colors.entrySet()) {
//            shifted.put(entry.getKey() + 1, entry.getValue());
//        }
//
//        this.colors.clear();
//        this.colors.putAll(shifted);
//    }

    public boolean isEmpty() {
        return this.colors.isEmpty();
    }

    public void clear() {
        this.colors.clear();
    }

    public synchronized Map<Integer, KobaColor> getColors() {
        return this.colors;
    }

    public boolean isEquals(KobaOutputColor other) {
        if (other == null) return false;

        if (this.colors.size() != other.colors.size()) return false;

        for (Map.Entry<Integer, KobaColor> entry : this.colors.entrySet()) {
            Integer key = entry.getKey();
            KobaColor thisColor = entry.getValue();
            if(!other.colors.containsKey(key)) return false;
            KobaColor otherColor = other.colors.get(key);

            if (otherColor == null) return false;
            if (!thisColor.isEquals(otherColor)) return false;
        }

        return true;
    }

    private final static KobaOutputColor offColors = new KobaOutputColor();

    public static KobaOutputColor createBlack(int ledCount) {
        offColors.clear();
        offColors.fill(ledCount, ColorConstants.OFF);
        return offColors;
    }
}
