/**
 *  Library helping to manage UI layers
 */
#Const Version    "2017-09-13"
#Const ScriptName "ManiaApps/Nadeo/Layers.Script.txt"

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
// Globales
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
declare Ident[Text] G_LibLayers_Layers; ///< Stock the registred layers ["LayerName" => #LayerId]

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
// Functions
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
// Public
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Return the version number of the script
 *
 *  @return                           The version number of the script
 */
Text GetScriptVersion() {
  return Version;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Return the name of the script
 *
 *  @return                           The name of the script
 */
Text GetScriptName() {
  return ScriptName;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Check if a layer really exists
 *
 *  @param  _LayerName                The name of the layer to check
 *
 *  @return                           True if the layer exists, false otherwise
 */
Boolean Exists(Text _LayerName) {
  return (
    G_LibLayers_Layers.existskey(_LayerName) &&
    UILayers.existskey(G_LibLayers_Layers[_LayerName])
  );
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Get a layer from its name
 *
 *  @param  _LayerName                The name of the layer to get
 *
 *  @return                           The layer if found, Null otherwise
 */
CUILayer Get(Text _LayerName) {
  if (!Exists(_LayerName)) return Null;
  return UILayers[G_LibLayers_Layers[_LayerName]];
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Destroy a layer
 *
 *  @param  _LayerName                The name of the layer to destroy
 */
Void Destroy(Text _LayerName) {
  if (!Exists(_LayerName)) return;
  UILayerDestroy(UILayers[G_LibLayers_Layers[_LayerName]]);
  declare Removed = G_LibLayers_Layers.removekey(_LayerName);
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/// Destroy all layers
Void DestroyAll() {
  foreach (LayerName => LayerId in G_LibLayers_Layers) {
    Destroy(LayerName);
  }
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Create a new layer
 *
 *  @param  _LayerName                The name of the layer to create
 *  @param  _LayerManialink           The content of the layer's manialink
 */
Void Create(Text _LayerName, Text _LayerManialink) {
  if (Exists(_LayerName)) Destroy(_LayerName);

  declare NewLayer <=> UILayerCreate();
  if (NewLayer != Null) {
    G_LibLayers_Layers[_LayerName] = NewLayer.Id;
    NewLayer.ManialinkPage = _LayerManialink;
  }
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Create a new layer
 *  If a layer with the same name already exists,
 *  destroys and replaces it
 *
 *  @param  _LayerName                The name of the layer to create
 */
Void Create(Text _LayerName) {
  Create(_LayerName, "");
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Update a layer manialink
 *
 *  @param  _LayerName                The name of the layer to update
 *  @param  _LayerManialink           The new manialink to use
 */
Void Update(Text _LayerName, Text _LayerManialink) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return;
  Layer.ManialinkPage = _LayerManialink;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Set the type of a layer
 *
 *  @param  _LayerName                The name of the layer
 *  @param  _LayerType                The type of layer to set
 */
Void SetType(Text _LayerName, CUILayer::EUILayerType _LayerType) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return;
  Layer.Type = _LayerType;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Set the Animation type of a layer (IN OUT ANIMATION)
 *
 *  @param  _LayerName                The name of the layer
 *  @param  _LayerType                The type of Animation to set
 */
Void SetAnimationType(Text _LayerName, CUILayer::EUILayerAnimation _LayerAnimation) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return;
  Layer.InOutAnimation = _LayerAnimation;
}
Void SetAnimationTypeOut(Text _LayerName, CUILayer::EUILayerAnimation _LayerAnimation) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return;
  Layer.OutAnimation = _LayerAnimation;
}
Void SetAnimationTypeIn(Text _LayerName, CUILayer::EUILayerAnimation _LayerAnimation) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return;
  Layer.InAnimation = _LayerAnimation;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Set the layer visibility
 *
 *  @param  _LayerName                The name of the layer to update
 *  @param  _IsVisible                True if the layer must be visible, false otherwise
 */
Void SetVisibility(Text _LayerName, Boolean _IsVisible) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return;
  Layer.IsVisible = _IsVisible;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Show the layer
 *
 *  @param  _LayerName                The name of the layer to show
 */
Void Show(Text _LayerName) {
  SetVisibility(_LayerName, True);
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Hide the layer
 *
 *  @param  _LayerName                The name of the layer to hide
 */
Void Hide(Text _LayerName) {
  SetVisibility(_LayerName, False);
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Check if a layer is visible
 *
 *  @param  _LayerName                The name of the layer to check
 *
 *  @return                           True if the layer is visible, False otherwise
 */
Boolean CheckVisible(Text _LayerName) {
  declare Layer <=> Get(_LayerName);
  if (Layer == Null) return False;
  return Layer.IsVisible;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Get the name of a layer
 *
 *  @param  _Layer                    The layer to get
 *
 *  @return                           The name of the layer if found
 *                                    An empty Text otherwise
 */
Text GetName(CUILayer _Layer) {
  if (_Layer != Null && G_LibLayers_Layers.exists(_Layer.Id)) return G_LibLayers_Layers.keyof(_Layer.Id);
  return "";
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/** Get the name of a layer
 *
 *  @param  _LayerId                  The  iflayer to get
 *
 *  @return                           The name of the layer if found
 *                                    An empty Text otherwise
 */
Text GetName(Ident _LayerId) {
  if (G_LibLayers_Layers.exists(_LayerId)) return G_LibLayers_Layers.keyof(_LayerId);
  return "";
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/// Unload the library
Void Unload() {
  DestroyAll();
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
/// Load the library
Void Load() {
  Unload();
}