//------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/vstrepresentation.h
// Created by  : Steinberg, 08/2010
// Description : VST Representation Helper
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------

#pragma once

#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivstrepresentation.h"

//------------------------------------------------------------------------
namespace Steinberg {
class IBStreamer;

namespace Vst {

//------------------------------------------------------------------------
/** Helper for XML Representation creation.
\ingroup vstClasses

Here an example of how to use this helper:
\n
\code{.cpp}
//------------------------------------------------------------------------
// here the parameter ids used by this example
enum {
    kGain = 129,
    kSize,
    kCutoff,
    kResonance,
    kMaster,
    kEnable1,
    kEnable2,
    kFrequency1,
    kFrequency2,
    kGain1,
    kGain2,
};

//------------------------------------------------------------------------
tresult PLUGIN_API MyPlugInController::getXmlRepresentationStream (Vst::RepresentationInfo& info,
IBStream* stream)
{
    String name (info.name);
    if (name == GENERIC_8_CELLS)
    {
        Vst::XmlRepresentationHelper helper (info, "My Company Name", "My Product Name", gPlugProcessorClassID, stream);

        helper.startPage ("Main Page");
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kGain);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kSize);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kMaster);
        helper.startEndCell ();	// empty cell
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kCutoff);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kResonance);
        helper.startEndCell ();	// empty cell
        helper.startEndCell ();	// empty cell
        helper.endPage ();

        helper.startPage ("Page 2");
        helper.startEndCellOneLayer (Vst::LayerType::kSwitch, kEnable1);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kFrequency1);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kGain1);
        helper.startEndCell ();	// empty
        helper.startEndCellOneLayer (Vst::LayerType::kSwitch, kEnable2);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kFrequency2);
        helper.startEndCellOneLayer (Vst::LayerType::kKnob, kGain2);
        helper.startEndCell ();	// empty
        helper.endPage ();

        return kResultTrue;
    }
    return kResultFalse;
}
\endcode
*/
class XmlRepresentationHelper
{
public:
	XmlRepresentationHelper (const RepresentationInfo& info, const FIDString companyName,
	                         const FIDString pluginName, const TUID& pluginUID, IBStream* stream);
	virtual ~XmlRepresentationHelper ();

	bool startPage (FIDString name, int32 unitID = -1); ///< Starts a Page before adding a Cell.
	bool endPage (); ///< Ends a Page before opening a new one.
	bool startCell (); ///< Starts a Cell before adding a Layer.
	bool endCell (); ///< Ends a Cell when no more layer needed.
	bool startEndCell (); ///< Creates an empty cell (alignment for example).

	/** Starts a layer for a given type (Vst::LayerType), a parameter id, optionally a function
	   (Vst::AttributesFunction) and a style (Vst::AttributesStyle). */
	bool startLayer (int32 type, int32 id, FIDString _function = nullptr, FIDString style = nullptr);

	/** Ends a layer before adding new one */
	bool endLayer ();

	/** Same than startLayer except that the layer will be ended automatically (no need to call
	 * endLayer). */
	bool startEndLayer (int32 type, int32 id, FIDString _function = nullptr, FIDString style = nullptr);

	/** Creates a Cell with 1 Layer and end it, could be only call after a call to startPage */
	bool startEndCellOneLayer (int32 type, int32 id, FIDString _function = nullptr, FIDString style = nullptr);

	/** Starts a layer for a given parameter info and an optional function
	 * (Vst::AttributesFunction). */
	bool startLayer (Vst::ParameterInfo& info, FIDString _function = nullptr);

	/** Same than startLayer with end created automatically. */
	bool startEndLayer (Vst::ParameterInfo& info, FIDString _function = nullptr);

	/** Creates a Cell with 1 Layer and end it, could be only call after a call to startPage. */
	bool startEndCellOneLayer (Vst::ParameterInfo& info, FIDString _function = nullptr);

	/** Creates a Cell with 1 Layer (with name) and end it, could be only call after a call to
	 * startPage. */
	bool startEndCellOneLayerWithParamName (Vst::ParameterInfo& info, FIDString _function = nullptr);

protected:
	enum
	{
		kInRepresentation = 0,
		kInPage,
		kInCell,
		kInLayer,
		kInTitleDisplay,
		kInName
	};

	bool startLayer (int32 type, int32 id, FIDString _function, FIDString style, bool ended);
	bool startLayer (Vst::ParameterInfo& info, FIDString _function, bool ended);

	bool startEndTitleDisplay (Vst::ParameterInfo& info);

	bool checkState (int32 newState);

	IPtr<IBStream> stream;
	int32 state;
};

//------------------------------------------------------------------------
} // namespace Vst
} // namespace Steinberg
