import { useEffect, useRef, useState } from 'react';

import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';

import {useRive, useStateMachineInput} from '../../src';
import {Button} from './components/Button';
import './rive-overview.css';

<Meta title="React Runtime/Playback Controls" />

# Animation Playback

When rendering Rives, you may want to control animation playback for certain scenarios. Animation playback allows you to programatically pause, stop, play, reset, and scrub animations as needed. You may find this useful for coordinating certain user interaction or other programatic cases to Rive animations.

**Note:** Just like the Rive web runtime, you invoke playback methods on a `rive` instance. Because of this, you will need to use the `useRive` method to render Rives to your React applications, as it returns a `rive` instance for you to invoke controls on.

## User event-driven playback

You can control Rive animation playback with user interaction directly on the canvas, or even outside the canvas, as you'll see below.

### Play/pause with hover

The example below shows how to start with a Rive instance that does not autoplay initially, but plays whenever the cursor is hovered over the canvas, and returns to a paused state when the mouse leaves the canvas.

<Canvas withSource="open">
  <Story name="Play/pause with hover">
    {() => {
      const { rive, RiveComponent } = useRive({
        src: 'poison-loader.riv',
        autoplay: false,
      });
      function onMouseEnter() {
        // rive will return as null until the file as fully loaded, so we include this
        // guard to prevent any unwanted errors.
        if (rive) {
          rive.play();
        }
      }
      function onMouseLeave() {
        if (rive) {
          rive.pause();
        }
      }
      return (
        <div className="center">
          <RiveComponent
            className="base-canvas-size"
            onMouseEnter={onMouseEnter}
            onMouseLeave={onMouseLeave}
          />
        </div>
      );
    }}
  </Story>
</Canvas>

<Canvas withSource="open">
  <Story name="Play/pause with intersection observer">
    {() => {
      const ref = useRef(null);
      const { rive, RiveComponent } = useRive({
        src: 'baseball.riv',
        autoplay: false,
        animations: "Hover"
      });
      useEffect(() => {
        const observer = new IntersectionObserver(
          ([things]) => {
            if (rive) {
              if (things.isIntersecting) {
                rive.play("Hover");
              } else {
                rive.pause("Hover");
              }
            }
          },
          {
            rootMargin: '0px',
            threshold: 0.1,
          }
        )
        if (ref && ref.current) {
          observer.observe(ref.current)
        }
      }, [rive]);
      return (
        <div ref={ref} className="center">
          <RiveComponent className="base-canvas-size" />
        </div>
      );
    }}
  </Story>
</Canvas>

## Play/pause with external elements

This example shows how you can control Rive elements via user interaction outside of the canvas, such as other buttons. Here, the play/pause button will toggle whether or not to play or pause the Rive animation.

<Canvas withSource="open">
  <Story name="Play/pause with external elements">
    {() => {
      const [isPlaying, setIsPlaying] = useState(true);
      const { rive, RiveComponent } = useRive({
        src: 'truck.riv',
        stateMachines: "drive",
        artboard: 'Truck',
        autoplay: true,
      });
      const togglePlaying = () => {
        if (isPlaying) {
          rive.pause();
          setIsPlaying(false);
        } else {
          rive.play();
          setIsPlaying(true);
        }
      };
      return ((
        <>
          <div className="center">
            <RiveComponent className="base-canvas-size" />
            <Button onClick={togglePlaying}>{isPlaying ? 'Pause' : 'Play'}</Button>
          </div>
        </>
      ));
    }}
  </Story>
</Canvas>

## Additional ways to control playback

While user interaction is a common way to control animation playback for Rives, there are other ways to achieve the same means as well.

### API-driven playback

Another common way to control animation playback is through API responses. Imagine an API that you poll for loading progress of a task. Based on that progress response, you may play or stop a given animation. As long as you hold a reference to the `rive` instance returned from the `useRive` hook, you can invoke control methods on that instance in places such as callbacks from API responses. 

