context: namespace Fabric.Internal.Editor.ThirdParty.xcodeapi.PBX
  {
  	using System.Collections.Generic;
  	using System.Collections;
  	using System.Text.RegularExpressions;
  	using System.IO;
  	using System.Linq;
  	using System;
  
      class PBXElement
      {
          protected PBXElement() {}
          
          // convenience methods
          public string AsString() { return ((PBXElementString)this).value; }
          public PBXElementArray AsArray() { return (PBXElementArray)this; }
          public PBXElementDict AsDict()   { return (PBXElementDict)this; }
          
          public PBXElement this[string key]
          {
              get { return AsDict()[key]; }
              set { AsDict()[key] = value; }
          }
      }
      
      class PBXElementString : PBXElement
      {
          public PBXElementString(string v) { value = v; }
          
          public string value;
      }
  
      class PBXElementDict : PBXElement
      {
          public PBXElementDict() : base() {}
          
          private SortedDictionary<string, PBXElement> m_PrivateValue = new SortedDictionary<string, PBXElement>();
          public IDictionary<string, PBXElement> values { get { return m_PrivateValue; }}
          
          new public PBXElement this[string key]
          {
              get {
                  if (values.ContainsKey(key))
                      return values[key];
                  return null;
              }
              set { this.values[key] = value; }
          }
          
          public bool Contains(string key)
          {
              return values.ContainsKey(key);
          }
          
          public void Remove(string key)
          {
              values.Remove(key);
          }
  
          public void SetString(string key, string val)
          {
              values[key] = new PBXElementString(val);
          }
          
          public PBXElementArray CreateArray(string key)
          {
              var v = new PBXElementArray();
              values[key] = v;
              return v;
          }
          
          public PBXElementDict CreateDict(string key)
          {
              var v = new PBXElementDict();
              values[key] = v;
              return v;
          }
      }
      
      class PBXElementArray : PBXElement
      {
          public PBXElementArray() : base() {}
          public List<PBXElement> values = new List<PBXElement>();
          
          // convenience methods
          public void AddString(string val)
          {
              values.Add(new PBXElementString(val));
          }
          
          public PBXElementArray AddArray()
          {
              var v = new PBXElementArray();
              values.Add(v);
              return v;
          }
          
          public PBXElementDict AddDict()
          {
              var v = new PBXElementDict();
              values.Add(v);
              return v;
          }
      }
  
      internal class PBXObject
      {   
          public string guid;
          protected PBXElementDict m_Properties = new PBXElementDict();
          
          internal void SetPropertiesWhenSerializing(PBXElementDict props)
          {
              m_Properties = props;
          }
          
          internal PBXElementDict GetPropertiesWhenSerializing() 
          { 
              return m_Properties; 
          }
          
          // returns null if it does not exist
          protected string GetPropertyString(string name)
          {
              var prop = m_Properties[name];
              if (prop == null)
                  return null;
  
              return prop.AsString();
          }
          
          protected void SetPropertyString(string name, string value)
          {
              if (value == null)
                  m_Properties.Remove(name);
              else
                  m_Properties.SetString(name, value);
          }
          
          protected List<string> GetPropertyList(string name)
          {
              var prop = m_Properties[name];
              if (prop == null)
                  return null;
              
              var list = new List<string>();
              foreach (var el in prop.AsArray().values)
                  list.Add(el.AsString());
              return list;
          }
          
          protected void SetPropertyList(string name, List<string> value)
          {
              if (value == null)
                  m_Properties.Remove(name);
              else
              {
                  var array = m_Properties.CreateArray(name);
                  foreach (string val in value)
                      array.AddString(val);
              }
          }
          
          private static PropertyCommentChecker checkerData = new PropertyCommentChecker();
          internal virtual PropertyCommentChecker checker { get { return checkerData; } }
          internal virtual bool shouldCompact { get { return false; } }
          
          public virtual void UpdateProps() {}      // Updates the props from cached variables
          public virtual void UpdateVars() {}       // Updates the cached variables from underlying props
      }
      
      internal class PBXBuildFile : PBXObject
      {
          public string fileRef;
          public string compileFlags;
          public bool weak;
          
          private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
              "fileRef/*"
          });
          internal override PropertyCommentChecker checker { get { return checkerData; } }
          internal override bool shouldCompact { get { return true; } }
          
          public static PBXBuildFile CreateFromFile(string fileRefGUID, bool weak,
                                                    string compileFlags)
          {
              PBXBuildFile buildFile = new PBXBuildFile();
              buildFile.guid = PBXGUID.Generate();
              buildFile.SetPropertyString("isa", "PBXBuildFile");
              buildFile.fileRef = fileRefGUID;
              buildFile.compileFlags = compileFlags;
              buildFile.weak = weak;
              return buildFile;
          }
          
          PBXElementDict GetSettingsDict()
          {
              if (m_Properties.Contains("settings"))
                  return m_Properties["settings"].AsDict();
              else
                  return m_Properties.CreateDict("settings");        
          }
          
          public override void UpdateProps()
          {
              SetPropertyString("fileRef", fileRef);
              if (compileFlags != null && compileFlags != "")
              {
                  GetSettingsDict().SetString("COMPILER_FLAGS", compileFlags);
              }
              if (weak)
              {
                  var dict = GetSettingsDict();
                  PBXElementArray attrs = null;
                  if (dict.Contains("ATTRIBUTES"))
                      attrs = dict["ATTRIBUTES"].AsArray();
                  else
                      attrs = dict.CreateArray("ATTRIBUTES");
                      
                  bool exists = false;
                  foreach (var value in attrs.values)
                  {
                      if (value is PBXElementString && value.AsString() == "Weak")
                          exists = true;
                  }
                  if (!exists)
                      attrs.AddString("Weak");
              }
          }
  
          public override void UpdateVars()
          {
              fileRef = GetPropertyString("fileRef");
              compileFlags = null;
              weak = false;
              if (m_Properties.Contains("settings"))
              {
                  var dict = m_Properties["settings"].AsDict();
                  if (dict.Contains("COMPILER_FLAGS"))
                      compileFlags = dict["COMPILER_FLAGS"].AsString();
                  
                  if (dict.Contains("ATTRIBUTES"))
                  {
                      var attrs = dict["ATTRIBUTES"].AsArray();
                      foreach (var value in attrs.values)
                      {
                          if (value is PBXElementString && value.AsString() == "Weak")
                              weak = true;
                      }
                  }
              }
          }
      }
      
      internal class PBXFileReference : PBXObject
      {
          public string path;
          public string name;
          public PBXSourceTree tree;
          
          internal override bool shouldCompact { get { return true; } }
          
          public static PBXFileReference CreateFromFile(string path, string projectFileName,
                                                        PBXSourceTree tree)
          {
              string guid = PBXGUID.Generate();
              
              PBXFileReference fileRef = new PBXFileReference();
              fileRef.SetPropertyString("isa", "PBXFileReference");
              fileRef.guid = guid;
              fileRef.path = path;
              fileRef.name = projectFileName;
              fileRef.tree = tree;
              return fileRef;
          }
          
          public override void UpdateProps()
          {
              string ext = null;
  
gt:             if (name != null) 