context: //
  //  VSQXDataFormat.cs - provides a DataFormat for manipulating synthesized audio in the XML-based Vocaloid VSQX format
  //
  //  Author:
  //       Michael Becker <alcexhim@gmail.com>
  //
  //  Copyright (c) 2011-2020 Mike Becker's Software
  //
  //  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/>.
  
  using System;
  using System.Collections.Generic;
  
  using UniversalEditor.DataFormats.Markup.XML;
  using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
  using UniversalEditor.ObjectModels.Multimedia.Audio.Voicebank;
  using UniversalEditor.ObjectModels.Markup;
  
  namespace UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid
  {
  	/// <summary>
  	/// Provides a <see cref="DataFormat" /> for manipulating synthesized audio in the XML-based Vocaloid VSQX format.
  	/// </summary>
  	public class VSQXDataFormat : XMLDataFormat
  	{
  		/// <summary>
  		/// Gets or sets the name of the vendor for the product that created this VSQX file.
  		/// </summary>
  		/// <value>The name of the vendor for the product that created this VSQX file.</value>
  		public string ProductVendor { get; set; } = String.Empty;
  		/// <summary>
  		/// Gets or sets the version of the product that created this VSQX file.
  		/// </summary>
  		/// <value>The version of the product that created this VSQX file.</value>
  		public Version ProductVersion { get; set; } = new Version(1, 0);
  
  		protected override DataFormatReference MakeReferenceInternal()
  		{
  			DataFormatReference dfr = new DataFormatReference(this.GetType());
  			dfr.Capabilities.Add(typeof(SynthesizedAudioObjectModel), DataFormatCapabilities.All);
  			return dfr;
  		}
  		protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
  		{
  			objectModels.Push(new MarkupObjectModel());
  		}
  		protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
  		{
  			MarkupObjectModel mom = objectModels.Pop() as MarkupObjectModel;
  			SynthesizedAudioObjectModel au = (objectModels.Pop() as SynthesizedAudioObjectModel);
  			if (au == null) throw new ObjectModelNotSupportedException();
  
  			MarkupTagElement tagVSQ3 = mom.Elements["vsq3"] as MarkupTagElement;
  			if (tagVSQ3 != null)
  			{
  				foreach (MarkupElement el in tagVSQ3.Elements)
  				{
  					MarkupTagElement tag = el as MarkupTagElement;
  					if (tag != null)
  					{
  						string text = tag.FullName;
  						if (text != null)
  						{
  							if (!(text == "vender"))
  							{
  								if (!(text == "version"))
  								{
  									if (text == "vsTrack")
  									{
  										SynthesizedAudioTrack track = new SynthesizedAudioTrack();
  										MarkupTagElement tagTrackName = tag.Elements["trackName"] as MarkupTagElement;
  										if (tagTrackName != null)
  										{
  											MarkupStringElement tagTrackNameCDATA = tagTrackName.Elements[0] as MarkupStringElement;
  											if (tagTrackNameCDATA != null)
  											{
  												track.Name = tagTrackNameCDATA.Value;
  											}
  										}
  										MarkupTagElement tagTrackComment = tag.Elements["comment"] as MarkupTagElement;
  										if (tagTrackComment != null)
  										{
  											MarkupStringElement tagTrackNameCDATA = tagTrackComment.Elements[0] as MarkupStringElement;
  											if (tagTrackNameCDATA != null)
  											{
  												track.Comment = tagTrackNameCDATA.Value;
  											}
  										}
  										foreach (MarkupElement el2 in tag.Elements)
  										{
  											MarkupTagElement tag2 = el2 as MarkupTagElement;
  											if (tag2 != null)
  											{
  												text = tag2.FullName;
  
  												switch (tag2.FullName)
  												{
  													case "musicalPart":
  													{
  														for (int j = 0; j < tag2.Elements.Count; j++)
  														{
  															MarkupTagElement tag3 = tag2.Elements[j] as MarkupTagElement;
  															if (tag3 == null) continue;
  
  															SynthesizedAudioCommand cmd = SynthesizedAudioCommandFromTag(tag3);
  															if (cmd != null)
  															{
  																track.Commands.Add(cmd);
  															}
  														}
  														break;
  													}
  												}
  
  												if (text != null)
  												{
  													if (!(text == "stylePlugin"))
  													{
  													}
  													else
  													{
  														Guid StylePluginID = Guid.Empty;
  														string StylePluginName = string.Empty;
  														Version StylePluginVersion = new Version(1, 0, 0, 0);
  														MarkupTagElement tagStylePluginID = tag2.Elements["stylePluginID"] as MarkupTagElement;
  														if (tagStylePluginID != null)
  														{
  															MarkupStringElement tagStylePluginIDCDATA = tagStylePluginID.Elements[0] as MarkupStringElement;
  															if (tagStylePluginIDCDATA != null)
  															{
  																try
  																{
  																	StylePluginID = new Guid(tagStylePluginIDCDATA.Value);
  																}
  																catch
  																{
  																}
  															}
  														}
  														MarkupTagElement tagStylePluginName = tag2.Elements["stylePluginName"] as MarkupTagElement;
  														if (tagStylePluginName != null)
  														{
  															MarkupStringElement tagStylePluginNameCDATA = tagStylePluginName.Elements[0] as MarkupStringElement;
  															if (tagStylePluginNameCDATA != null)
  															{
  																StylePluginName = tagStylePluginNameCDATA.Value;
  															}
  														}
  														MarkupTagElement tagStylePluginVersion = tag2.Elements["version"] as MarkupTagElement;
  														if (tagStylePluginVersion != null)
  														{
  															MarkupStringElement tagStylePluginVersionCDATA = tagStylePluginVersion.Elements[0] as MarkupStringElement;
  															if (tagStylePluginVersionCDATA != null)
  															{
  																StylePluginVersion = new Version(tagStylePluginVersionCDATA.Value);
  															}
  														}
  														SynthesizedAudioStylePlugin plugin = new SynthesizedAudioStylePlugin();
  														plugin.ID = StylePluginID;
  														plugin.Name = StylePluginName;
  														plugin.Version = StylePluginVersion;
  													}
  												}
  											}
  										}
  										au.Tracks.Add(track);
  									}
  								}
  								else
  								{
  									MarkupStringElement tagCDATA = tag.Elements[0] as MarkupStringElement;
  									if (tagCDATA != null)
  									{
  										ProductVersion = new Version(tagCDATA.Value);
  									}
  								}
  							}
  							else
  							{
  								MarkupStringElement tagCDATA = tag.Elements[0] as MarkupStringElement;
  								if (tagCDATA != null)
  								{
  									ProductVendor = tagCDATA.Value;
  								}
  							}
  						}
  					}
  				}
  			}
  		}
  
  		private SynthesizedAudioCommand SynthesizedAudioCommandFromTag(MarkupTagElement tag3)
  		{
  			switch (tag3.FullName)
  			{
  				case "note":
  				{
  					SynthesizedAudioCommandNote note = new SynthesizedAudioCommandNote();
  					MarkupTagElement tagPosTick = tag3.Elements["posTick"] as MarkupTagElement;
  					if (tagPosTick != null)
  					{
  						int posTick = 0;
  						if (int.TryParse(tagPosTick.Value, out posTick))
  						{
  							note.Position = posTick;
  						}
  					}
  					MarkupTagElement tagDurTick = tag3.Elements["durTick"] as MarkupTagElement;
  					if (tagDurTick != null)
  					{
  						int durTick = 0;
  						if (int.TryParse(tagDurTick.Value, out durTick))
  						{
  							note.Length = durTick;
  						}
  					}
  					MarkupTagElement tagNoteNum = tag3.Elements["noteNum"] as MarkupTagElement;
  					if (tagNoteNum != null)
  					{
  						int noteNum = 0;
  						if (int.TryParse(tagNoteNum.Value, out noteNum))
  						{
  							note.Frequency = noteNum;
  						}
  					}
  					MarkupTagElement tagVelocity = tag3.Elements["velocity"] as MarkupTagElement;
  					if (tagVelocity != null)
  					{
  						int velocity = 0;
  						if (int.TryParse(tagVelocity.Value, out velocity))
  						{
  							note.Intensity = velocity;
  						}
  					}
  					MarkupTagElement tagLyric = tag3.Elements["lyric"] as MarkupTagElement;
  					if (tagLyric != null)
  					{
  						MarkupStringElement tagLyricCDATA = tagLyric.Elements[0] as MarkupStringElement;
  						if (tagLyricCDATA != null)
  						{
  							note.Lyric = tagLyricCDATA.Value;
  						}
  					}
  					MarkupTagElement tagPhoneme = tag3.Elements["phnms"] as MarkupTagElement;
  					if (tagPhoneme != null)
  					{
  						MarkupStringElement tagPhonemeCDATA = tagPhoneme.Elements[0] as MarkupStringElement;
  						if (tagPhonemeCDATA != null)
  						{
  							note.Phoneme = tagPhonemeCDATA.Value;
  						}
  					}
  					MarkupTagElement tagNoteStyle = tag3.Elements["noteStyle"] as MarkupTagElement;
  					if (tagNoteStyle != null)
  					{
  						foreach (MarkupElement elAttr in tagNoteStyle.Elements)
  						{
  							MarkupTagElement tagAttr = elAttr as MarkupTagElement;
  							if (tagAttr != null)
  							{
  								if (tagAttr.Attributes["id"] != null)
  								{
  									if (tagAttr.Name == "attr")
  									{
  										switch (tagAttr.Attributes["id"].Value)
  										{
  											case "accent":
  											{
  												string value = tagAttr.Value;
  												int realValue = 50;
  												int.TryParse(value, out realValue);
  												note.Accent = realValue;
  												break;
  											}
  											case "bendDep":
  											{
  												string value = tagAttr.Value;
  												int realValue = 8;
  												int.TryParse(value, out realValue);
  												note.PitchBendDepth = realValue;
  												break;
  											}
  											case "bendLen":
  											{
  												string value = tagAttr.Value;
  												int realValue = 0;
  												int.TryParse(value, out realValue);
  												note.PitchBendLength = realValue;
  												break;
  											}
  											case "decay":
  											{
  												string value = tagAttr.Value;
  												int realValue = 50;
  												int.TryParse(value, out realValue);
  												note.Decay = realValue;
  												break;
  											}
  											case "fallPort":
  											{
  												string value = tagAttr.Value;
  												bool realValue2 = false;
  												bool.TryParse(value, out realValue2);
  												note.PortamentoFalling = realValue2;
  												break;
  											}
  											case "opening":
  											{
  												string value = tagAttr.Value;
  												int realValue = 127;
  												int.TryParse(value, out realValue);
  												note.Opening = realValue;
  												break;
  											}
  											case "risePort":
  											{
  												string value = tagAttr.Value;
  												bool realValue2 = false;
  												bool.TryParse(value, out realValue2);
  												note.PortamentoRising = realValue2;
  												break;
  											}
  											case "vibLen":
  											{
  												string value = tagAttr.Value;
  												int realValue = 66;
  												int.TryParse(value, out realValue);
  												note.VibratoLength = realValue;
  												break;
  											}
  											case "vibType":
  											{
  												string value = tagAttr.Value;
  												SynthesizedAudioVibratoType realValue3 = SynthesizedAudioVibratoType.None;
  												try
  												{
  													realValue3 = (SynthesizedAudioVibratoType)Enum.Parse(typeof(SynthesizedAudioVibratoType), value);
  												}
  												catch
  												{
  												}
  												note.VibratoType = realValue3;
  												break;
  											}
  										}
  									}
  									else
  									{
  										if (tagAttr.FullName == "seqAttr")
  										{
  											if (tagAttr.Attributes["id"] != null)
  											{
  												switch (tagAttr.Attributes["id"].Value)
  												{
  													case "vibRate":
  													{
  														MarkupTagElement tagPosNrm = tagAttr.FindElement(new string[]
  														{
  																									"elem",
  																									"posNrm"
  														}) as MarkupTagElement;
  														MarkupTagElement tagElv = tagAttr.FindElement(new string[]
  														{
  																									"elem",
  																									"elv"
  														}) as MarkupTagElement;
  														if (tagPosNrm != null)
  														{
  															int posNrm = 0;
  															int.TryParse(tagPosNrm.Value, out posNrm);
  														}
  														if (tagElv != null)
  														{
  															int elv = 0;
  															int.TryParse(tagElv.Value, out elv);
  														}
  														break;
  													}
  													case "vibDep":
  													{
  														MarkupTagElement tagPosNrm = tagAttr.FindElement(new string[]
  														{
  																								"elem",
  																								"posNrm"
  														}) as MarkupTagElement;
  														MarkupTagElement tagElv = tagAttr.FindElement(new string[]
  														{
  																								"elem",
  																								"elv"
  														}) as MarkupTagElement;
  														if (tagPosNrm != null)
  														{
  															int posNrm = 0;
  															int.TryParse(tagPosNrm.Value, out posNrm);
  														}
  														if (tagElv != null)
  														{
  															int elv = 0;
  															int.TryParse(tagElv.Value, out elv);
  														}
  														break;
  													}
  												}
  											}
  										}
  									}
  								}
  							}
  						}
  					}
  					return note;
  				}
  			}
  			return null;
  		}
  
  		protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
  		{
  			SynthesizedAudioObjectModel au = objectModels.Pop() as SynthesizedAudioObjectModel;
  			MarkupObjectModel mom = new MarkupObjectModel();
  			MarkupPreprocessorElement xml = new MarkupPreprocessorElement();
  			xml.Name = "xml";
  			xml.Value = "version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"";
  			mom.Elements.Add(xml);
  			MarkupTagElement tagVSQ3 = new MarkupTagElement();
  			tagVSQ3.Name = "vsq3";
  			tagVSQ3.Attributes.Add("xmlns", "http://www.yamaha.co.jp/vocaloid/schema/vsq3/");
  			tagVSQ3.Attributes.Add("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
  			tagVSQ3.Attributes.Add("xsi:schemaLocation", "http://www.yamaha.co.jp/vocaloid/schema/vsq3/vsq3.xsd");
  
gt: 			MarkupTagElement tagVender = new MarkupTagElement();