package com.gabrielavara.choiceplayer.controls.toast;

import static com.gabrielavara.choiceplayer.Constants.ALBUM_ART_SIZE;

import java.io.IOException;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gabrielavara.choiceplayer.controls.albumart.AlbumArt;
import com.gabrielavara.choiceplayer.dto.Mp3;
import com.gabrielavara.choiceplayer.util.ImageUtil;

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.SequentialTransition;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.util.Duration;

public class Toast {
    private static final String COULD_NOT_LOAD = "Could not load toast";
    private static Logger log = LoggerFactory.getLogger("com.gabrielavara.choiceplayer.controls.toast.Toast");

    @FXML
    public HBox hBox;
    @FXML
    public AlbumArt albumArt;
    @FXML
    public Label artistLabel;
    @FXML
    public Label titleLabel;
    @FXML
    private AnchorPane root;

    private boolean isShowed;
    private ToastStage stage;
    private SequentialTransition sequentialTransition;
    private Timeline showAnimation;
    private Timeline dismissAnimation;

    public Toast() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/controls/toast.fxml"));
            fxmlLoader.setController(this);
            fxmlLoader.load();
            initStage();
        } catch (IOException e) {
            log.error(COULD_NOT_LOAD);
            throw new IllegalStateException(COULD_NOT_LOAD, e);
        }
    }

    private void initStage() {
        stage = new ToastStage(root);
        stage.setScene(new Scene(root));
        stage.setAlwaysOnTop(true);
        stage.setLocation(stage.getBottomRight());
        stage.show();

        albumArt.setHoverAllowed(false);

        showAnimation = setupShowAnimation();
        dismissAnimation = setupDismissAnimation();
        sequentialTransition = new SequentialTransition(showAnimation, dismissAnimation);
    }

    public void setItems(Mp3 mp3) {
        artistLabel.setText(mp3.getArtist());
        titleLabel.setText(mp3.getTitle());

        Optional<byte[]> albumArtData = mp3.getAlbumArt();
        Image image = ImageUtil.getAlbumArt(albumArtData, ALBUM_ART_SIZE);
        albumArt.setImage(image);
    }

    private Timeline setupShowAnimation() {

        Timeline tl = new Timeline();

        double offScreenX = stage.getOffScreenBounds().getX();
        KeyValue kvX = new KeyValue(stage.xLocationProperty(), offScreenX);
        KeyFrame frame1 = new KeyFrame(Duration.ZERO, kvX);

        Interpolator interpolator = Interpolator.TANGENT(Duration.millis(300), 50);
        KeyValue kvInter = new KeyValue(stage.xLocationProperty(), stage.getBottomRight().getX(), interpolator);
        KeyFrame frame2 = new KeyFrame(Duration.millis(1300), kvInter);

        KeyValue kvOpacity = new KeyValue(stage.opacityProperty(), 0.0);
        KeyFrame frame3 = new KeyFrame(Duration.ZERO, kvOpacity);

        KeyValue kvOpacity2 = new KeyValue(stage.opacityProperty(), 1.0);
        KeyFrame frame4 = new KeyFrame(Duration.millis(1000), kvOpacity2);

        tl.getKeyFrames().addAll(frame1, frame2, frame3, frame4);

        tl.setOnFinished(e -> isShowed = true);

        return tl;
    }

    private Timeline setupDismissAnimation() {

        Timeline tl = new Timeline();

        double offScreenX = stage.getOffScreenBounds().getX();
        Interpolator interpolator = Interpolator.TANGENT(Duration.millis(300), 50);
        double trayPadding = 3;

        KeyValue kvX = new KeyValue(stage.xLocationProperty(), offScreenX + trayPadding, interpolator);
        KeyFrame frame1 = new KeyFrame(Duration.millis(1400), kvX);

        KeyValue kvOpacity = new KeyValue(stage.opacityProperty(), 0.4);
        KeyFrame frame2 = new KeyFrame(Duration.millis(2000), kvOpacity);

        tl.getKeyFrames().addAll(frame1, frame2);

        tl.setOnFinished(e -> {
            isShowed = false;
            stage.close();
            stage.setLocation(stage.getBottomRight());
        });

        return tl;
    }

    public void showAndDismiss() {
        if (isShowed) {
            dismiss();
        } else {
            stage.show();
            playSequential();
        }
    }

    private void dismiss() {
        if (isShowed) {
            playDismissAnimation();
        }
    }

    private void playDismissAnimation() {
        dismissAnimation.play();
    }

    private void playSequential() {
        sequentialTransition.getChildren().get(1).setDelay(Duration.seconds(3));
        sequentialTransition.play();
    }

}

@@ -117,16 +117,90 @@
 RT_SIZE;
+%0Aimport static com.gabrielavara.choiceplayer.Constants.ANIMATION_DURATION;
 %0A%0Aimport
@@ -476,46 +476,8 @@
 l;%0A%0A
-import javafx.animation.Interpolator;%0A
 impo
@@ -2902,92 +2902,8 @@
 );%0A%0A
-        Interpolator interpolator = Interpolator.TANGENT(Duration.millis(300), 50);%0A
     
@@ -2994,30 +2994,16 @@
 ).getX()
-, interpolator
 );%0A     
@@ -3056,12 +3056,26 @@
 lis(
-1300
+ANIMATION_DURATION
 ), k
@@ -3357,12 +3357,26 @@
 lis(
-1000
+ANIMATION_DURATION
 ), k
@@ -3684,92 +3684,8 @@
 ();%0A
-        Interpolator interpolator = Interpolator.TANGENT(Duration.millis(300), 50);%0A
     
@@ -3804,22 +3804,8 @@
 ding
-, interpolator
 );%0A 
@@ -3862,12 +3862,26 @@
 lis(
-1400
+ANIMATION_DURATION
 ), k
@@ -4018,12 +4018,26 @@
 lis(
-2000
+ANIMATION_DURATION
 ), k

set animation duration for Toast animation