/*
 * MIT License
 *
 * Copyright (c) 2021 Jannis Weis
 *
 * 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 com.github.weisj.darklaf.ui.tree;

import java.awt.*;

import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.TreePath;

import com.github.weisj.darklaf.graphics.LegacyAnimator;

public class DarkTreeExpansionAnimationListener implements TreeExpansionListener {

    private final JTree tree;
    private final TreeStateAnimator animator;

    public DarkTreeExpansionAnimationListener(final JTree tree) {
        this.tree = tree;
        this.animator = new TreeStateAnimator();
        animator.setEnabled(UIManager.getBoolean("Tree.iconAnimations"));
        tree.addTreeExpansionListener(this);
    }

    public void install() {
        this.tree.addTreeExpansionListener(this);
    }

    public void uninstall() {
        animator.dispose();
        this.tree.removeTreeExpansionListener(this);
    }

    @Override
    public void treeExpanded(final TreeExpansionEvent event) {
        startAnimation(event.getPath());
    }

    @Override
    public void treeCollapsed(final TreeExpansionEvent event) {
        startAnimation(event.getPath());
    }

    public void startAnimation(final TreePath path) {
        if (!animator.isEnabled()) return;
        animator.state = 0;
        animator.path = path;
        animator.animationRow = tree.getRowForPath(path);
        boolean running = animator.isRunning();
        animator.suspend();
        if (running) {
            // Forces paintCycleEnd to be called.
            animator.resume(animator.getTotalFrames(), false);
        }
        animator.resume(0, false, tree);
    }

    public TreePath getAnimationPath() {
        return animator.path;
    }

    public float getAnimationState() {
        return animator.state;
    }

    protected class TreeStateAnimator extends LegacyAnimator {

        private static final int DURATION = 60;
        private static final int RESOLUTION = 10;

        private TreePath path;
        private float state;
        private int animationRow;

        public TreeStateAnimator() {
            super(DURATION / RESOLUTION, DURATION, 0);
        }

        private void repaint() {
            if (animationRow >= 0) {
                Rectangle bounds = tree.getRowBounds(animationRow);
                bounds.x = 0;
                bounds.width = tree.getWidth();
                tree.paintImmediately(bounds);
            }
        }

        @Override
        public void paintNow(final float fraction) {
            state = fraction;
            repaint();
        }

        @Override
        protected void paintCycleEnd() {
            super.paintCycleEnd();
            state = 1;
            repaint();
            animationRow = -1;
        }
    }
}

@@ -1375,22 +1375,16 @@
 raphics.
-Legacy
 Animator
@@ -1950,15 +1950,12 @@
 tor.
-dispose
+stop
 ();%0A
@@ -2490,256 +2490,49 @@
     
-boolean running = animator.isRunning();%0A        animator.suspend();%0A        if (running) %7B%0A            // Forces paintCycleEnd to be called.%0A            animator.resume(animator.getTotalFrames(), false);%0A        %7D%0A        animator.resume(0, false, 
+animator.stop();%0A        animator.resume(
 tree
@@ -2746,14 +2746,8 @@
 nds 
-Legacy
 Anim
@@ -2758,107 +2758,8 @@
  %7B%0A%0A
-        private static final int DURATION = 60;%0A        private static final int RESOLUTION = 10;%0A%0A
     
@@ -2908,41 +2908,9 @@
 per(
-DURATION / RESOLUTION, DURATION, 
+6
 0);%0A
@@ -3255,18 +3255,23 @@
 aint
-Now(final 
+AnimationFrame(
 floa
@@ -3393,60 +3393,31 @@
 oid 
-paintCycleEnd() %7B%0A            super.paintCycleEnd();
+onAnimationFinished() %7B
 %0A   

Replace tree expansion animator with a new animator implementation