
import React from 'react';
import { ContentPage } from '../../components/ContentPage';
import { InfoPanel } from '../../components/InfoPanel';
import { ApiSection } from '../../types';

const watchApi: ApiSection[] = [
  {
    title: 'Chemical.Watch',
    description: 'A utility function that creates an observer for a reactive source (Value or Computed) and immediately runs a callback when the source changes. It provides a simpler API for common observation tasks compared to manually using `Chemical.Observer`.',
    entries: [
      {
        signature: 'Chemical.Watch<T>(source: Value<T> | Computed<T>, watchCallback: (newValue: T, oldValue: T) -> ()): WatchHandle',
        description: 'Creates a watcher that runs the `watchCallback` whenever the `source` reactive object changes.',
        parameters: [
          { name: 'source', type: 'Value<T> | Computed<T>', description: 'The reactive Value or Computed object to watch.' },
          { name: 'watchCallback', type: '(newValue: T, oldValue: T) -> ()', description: 'The function to execute when the source changes. It receives the new and old values.' },
        ],
        returns: { type: 'WatchHandle', description: 'A handle object with a `:destroy()` method to stop watching.' },
        example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Value = Chemical.Value
local Computed = Chemical.Computed
local Watch = Chemical.Watch

local playerName = Value("Player1")
local health = Value(100)

local watchHandleName = Watch(playerName, function(newName, oldName)
  print("Watch (Name): Name changed from '" .. oldName .. "' to '" .. newName .. "'")
end)

local derivedStatus = Computed(function()
  return playerName:get() .. " - Health: " .. health:get()
end)

local watchHandleStatus = Watch(derivedStatus, function(newStatus, oldStatus)
  print("Watch (Status): Status changed from '" .. oldStatus .. "' to '" .. newStatus .. "'")
end)


playerName:set("Champion")
-- Output (Watch Name): Player name changed from 'Player1' to 'Champion' (immediately)
-- Output (Watch Status): (after scheduler runs for Computed) Status changed from 'Player1 - Health: 100' to 'Champion - Health: 100'

health:set(80)
-- Output (Watch Status): (after scheduler runs for Computed) Status changed from 'Champion - Health: 100' to 'Champion - Health: 80'


-- To stop watching:
watchHandleName:destroy()
watchHandleStatus:destroy()
        `,
      },
    ],
  },
  {
    title: 'WatchHandle Methods',
    entries: [
      {
        signature: 'watchHandle:destroy()',
        description: 'Stops the watcher, disconnecting the underlying observer and preventing the `watchCallback` from being called on future changes to the source.',
        example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Value = Chemical.Value
local Watch = Chemical.Watch

local score = Value(100)
local handle = Watch(score, function(newScore) print("Score:", newScore) end)

score:set(110) -- Prints "Score: 110"
handle:destroy()
score:set(120) -- Does not print
        `,
        },
      ],
    }
];

export const WatchPage: React.FC = () => {
  return (
    <ContentPage title="Chemical.Watch" sections={watchApi}>
      <InfoPanel type="note" title="Execution Timing">
        <ul>
          <li className="mb-1">
            When watching a <code>Chemical.Value</code>, the <code>watchCallback</code> is executed
            <strong> immediately and synchronously</strong> when the Value is updated via <code>:set()</code>.
          </li>
          <li>
            When watching a <code>Chemical.Computed</code>, the <code>watchCallback</code> is executed
            <strong> immediately and synchronously</strong> when the <code>Computed</code> value itself
            <strong> settles</strong> on its new value. Remember that <code>Computed</code> values update
            asynchronously as part of the Chemical scheduler's batch processing.
          </li>
        </ul>
      </InfoPanel>
    </ContentPage>
  );
};
