package me.koba1.led.animations.audio.bass;

import com.fasterxml.jackson.annotation.JsonIgnore;
import me.koba1.led.animations.ColoredAnimation;
import me.koba1.led.animations.audio.Audio;
import me.koba1.led.audio.AudioProcessor;
import me.koba1.led.audio.BandType;
import me.koba1.led.model.LedStrip;
import me.koba1.led.model.colors.AnimationColor;
import me.koba1.led.model.colors.AnimationColorType;
import me.koba1.led.model.colors.KobaColor;
import me.koba1.led.model.colors.KobaOutputColor;
import me.koba1.led.utils.ColorConstants;
import me.koba1.led.utils.ColorUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class BassTrebleAnimation extends ColoredAnimation implements Audio {

    private final KobaColor white = ColorConstants.WHITE.clone();

    private float threshold;
    private long fadeOutTime;

    @JsonIgnore
    private long fadeOutStateBass;

    @JsonIgnore
    private long fadeOutStateTreble;

    public BassTrebleAnimation(float threshold, long fadeOutTime, Map<AnimationColorType, AnimationColor> colors) {
        super(103, colors);
        this.threshold = threshold;
        this.fadeOutTime = fadeOutTime;
        this.fadeOutStateBass = 0;
        this.fadeOutStateTreble = 0;
    }

    @Override
    public KobaOutputColor getColors(LedStrip ledStrip) {
        return null;
    }

    @Override
    public KobaOutputColor getColors(LedStrip ledStrip, AudioProcessor.AudioState s) {
        long unixTime = System.currentTimeMillis();
        outputColors.clear();
        AnimationColor bg = this.colors.get(AnimationColorType.BACKGROUND);
        AnimationColor fg = this.colors.get(AnimationColorType.FOREGROUND);
        //outputColors.fill(bg.getColor(ledStrip.getLedCount()));

        float bass = s.bands.get(BandType.BASS) > s.bands.get(BandType.SUB_BASS) ? s.bands.get(BandType.BASS) : s.bands.get(BandType.SUB_BASS);
        float treble = s.bands.get(BandType.TREBLE);
        float air = s.bands.get(BandType.AIR);

        List<KobaColor> colors = fg.getColor(ledStrip.getLedCount());

        if (bass >= this.threshold && (treble < this.threshold && air < this.threshold)) {
            this.fadeOutStateBass = unixTime + this.fadeOutTime;
            this.fadeOutStateTreble = 0;
        } else if (treble >= this.threshold && air >= this.threshold) {
            this.fadeOutStateTreble = unixTime + this.fadeOutTime;
            this.fadeOutStateBass = 0;
        }

        if (this.fadeOutStateBass >= unixTime) {
            long millisDiff = this.fadeOutStateBass - unixTime;

            List<KobaColor> newColors = new ArrayList<>();
            for (KobaColor color : colors) {
                int alpha = (int) ((float) millisDiff / this.fadeOutTime * color.getAlpha());
                newColors.add(color.withAlpha(alpha));
            }
            outputColors.fill(newColors);
        }

        if (this.fadeOutStateTreble >= unixTime) {
            long millisDiff = this.fadeOutStateTreble - unixTime;

            List<KobaColor> newColors = new ArrayList<>();
            int alpha = (int) ((float) millisDiff / this.fadeOutTime * 255);
            for (int i = 0; i < ledStrip.getLedCount(); i++) {
                newColors.add(white.withAlpha(alpha));
            }
            outputColors.fill(newColors);

//            int alpha = (int) ((float) millisDiff / this.fadeOutTime * 255);
//            white.setAlpha(alpha);
//            outputColors.fill(ledStrip.getLedCount(), white);
//            System.out.println("Output alpha: " + alpha + " " + white.getAlpha());
        }


        KobaOutputColor difference = ColorUtils.getDifference(this.previousColors, outputColors);
        this.previousColors.set(this.outputColors);
        return difference;
    }

    static {
        register(() -> new BassTrebleAnimation(
                0.9f,
                500,
                Map.of(AnimationColorType.FOREGROUND, new AnimationColor(),
                        AnimationColorType.BACKGROUND, new AnimationColor().type(AnimationColor.ColorType.GRADIENT))));
    }
}