/***

  Olive - Non-Linear Video Editor
  Copyright (C) 2022 Olive Team
  Modifications Copyright (C) 2025 mikesolar

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.

***/

#ifndef TRANSITIONBLOCK_H
#define TRANSITIONBLOCK_H

#include "node/block/block.h"

namespace olive
{

class ClipBlock;

class TransitionBlock : public Block {
	Q_OBJECT
public:
	TransitionBlock();

	virtual void Retranslate() override;

	rational in_offset() const;
	rational out_offset() const;

	/**
   * @brief Return the "middle point" of the transition, relative to the transition
   *
   * Used to calculate in/out offsets.
   *
   * 0 means the center of the transition is right in the middle and the in and out offsets will
   * be equal.
   */
	rational offset_center() const;
	void set_offset_center(const rational &r);

	void set_offsets_and_length(const rational &in_offset,
								const rational &out_offset);

	bool is_dual_transition() const
	{
		return connected_out_block() && connected_in_block();
	}

	Block *connected_out_block() const;
	Block *connected_in_block() const;

	double GetTotalProgress(const double &time) const;
	double GetOutProgress(const double &time) const;
	double GetInProgress(const double &time) const;

	virtual void Value(const NodeValueRow &value, const NodeGlobals &globals,
					   NodeValueTable *table) const override;

	virtual void InvalidateCache(
		const TimeRange &range, const QString &from, int element = -1,
		InvalidateCacheOptions options = InvalidateCacheOptions()) override;

	static const QString kOutBlockInput;
	static const QString kInBlockInput;
	static const QString kCurveInput;
	static const QString kCenterInput;

protected:
	virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob *job) const
	{
	}

	virtual void SampleJobEvent(const SampleBuffer &from_samples,
								const SampleBuffer &to_samples,
								SampleBuffer &out_samples, double time_in) const
	{
	}

	double TransformCurve(double linear) const;

	virtual void InputConnectedEvent(const QString &input, int element,
									 Node *output) override;

	virtual void InputDisconnectedEvent(const QString &input, int element,
										Node *output) override;

	virtual TimeRange InputTimeAdjustment(const QString &input, int element,
										  const TimeRange &input_time,
										  bool clamp) const override;

	virtual TimeRange
	OutputTimeAdjustment(const QString &input, int element,
						 const TimeRange &input_time) const override;

private:
	enum CurveType { kLinear, kExponential, kLogarithmic };

	double GetInternalTransitionTime(const double &time) const;

	void InsertTransitionTimes(AcceleratedJob *job, const double &time) const;

	ClipBlock *connected_out_block_;

	ClipBlock *connected_in_block_;
};

}

#endif // TRANSITIONBLOCK_H
