//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Collections.Generic;

namespace CommonHelpers {

//**************************************************************************************************
partial class HXmlConfigurationBase {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ArgumentNullException" />
/// <exception cref="FileNotFoundException" />
/// <exception cref="HXmlConfigurationException" />
protected void LoadDocument(string filePath)
{
   HArgChecking.VerifyNotNull( filePath );
   LoadDocumentEx( filePath, null );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="HXmlConfigurationException" />
protected void LoadDocumentFromText(string xml)
{
   HArgChecking.VerifyNotNull( xml );
   LoadDocumentWithReader( new StringReader( xml ) );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="HXmlConfigurationException" />
protected void LoadDocumentWithReader(TextReader input)
{
   HArgChecking.VerifyNotNull( input );
   LoadDocumentEx( null, input );
}

//--------------------------------------------------------------------------------------------------

protected void UnloadDocument()
{
   _Document_ = null;
   _CurrentElement_ = null;
   _CurrentAttributeValues_ = null;
   _NamespaceManager_ = null;
   _FilePath_ = _FileFullPath_ = null;
}

//==================================================================================================

/// <exception cref="InvalidOperationException" />
/// <exception cref="HXmlConfigurationException" />
protected void SaveDocument()
{
   if ( FilePath == null )
      throw new InvalidOperationException(
         Verbose.FILE_PATH_WAS_NOT_SET_FOR_DOCUMENT_SAVING_OF_XML_CONFIGURATION );
   SaveDocument( FileFullPath );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="HXmlConfigurationException" />
protected void SaveDocument(string filePath)
{
   SaveDocument( filePath, false );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="HXmlConfigurationException" />
protected void SaveDocument(string filePath,bool setFilePath)
{
   HArgChecking.VerifyNotNull( filePath );
   VerifyDocumentLoaded();
   string
      fileFullPath = null;
   try
   {
      fileFullPath = Path.GetFullPath( filePath );
      ValidateDocument();
      Document.Save( fileFullPath );
   }
   catch (Exception e)
   {
      throw new HXmlConfigurationException( e.Message );
   }
   if ( setFilePath )
   {
      _FilePath_ = filePath;
      _FileFullPath_ = fileFullPath;
   }
}

//==================================================================================================

/// <exception cref="ArgumentNullException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="HXmlConfigurationException" />
protected void SetFilePath(string filePath)
{
   HArgChecking.VerifyNotNull( filePath );
   VerifyDocumentLoaded();
   string
      fileFullPath;
   try
   {
      fileFullPath = Path.GetFullPath( filePath );
   }
   catch (Exception e)
   {
      throw new HXmlConfigurationException(ComposeErrorMessageWithFile(
         e.Message, filePath ));
   }
   _FilePath_ = filePath;
   _FileFullPath_ = fileFullPath;
}

//--------------------------------------------------------------------------------------------------

protected void ResetFilePath()
{
   _FilePath_ = _FileFullPath_ = null;
}

//==================================================================================================

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
/// <exception cref="FileNotFoundException" />
/// <exception cref="HXmlConfigurationException" />
void LoadDocumentEx([HOptional] string filePath,[HOptional] TextReader input)
{
   if ( filePath == null )
      HArgChecking.VerifyNotNull( input );
   if ( input == null )
      HArgChecking.VerifyNotNull( filePath );
   if ( filePath != null && input != null )
      throw HArgChecking.ArgumentException_IncorrectArguments;

   UnloadDocument();

   var schemaSet = new XmlSchemaSet();
   var readerSettings = new XmlReaderSettings();

   schemaSet.Add( Schema );

   readerSettings.ValidationType = ValidationType.Schema;
   readerSettings.Schemas = schemaSet;

   var document = new XmlDocument();
   XmlNamespaceManager namespaceManager;

   string fileFullPath = null;

   try
   {
      if ( filePath != null )
         fileFullPath = Path.GetFullPath( filePath );
      using ( var reader = input!=null ?
         XmlReader.Create( input, readerSettings ) :
         XmlReader.Create( fileFullPath, readerSettings ) )
         document.Load( reader );

      if ( document.DocumentElement.NamespaceURI != Schema.TargetNamespace )
         throw HXmlConfigExceptionCreator.Create(
            Verbose.ELEMENT_OF_XML_DOCUMENT_MUST_BELONG_TO_THE_FOLLOWING_NAMESPACE_0,
            Schema.TargetNamespace );

      namespaceManager = new XmlNamespaceManager( document.NameTable );
      namespaceManager.AddNamespace( "x", Schema.TargetNamespace );
   }
   catch (Exception e)
   {
      if (e is FileNotFoundException)
         throw;
      throw new HXmlConfigurationException(ComposeErrorMessageWithFile(
         fileFullPath ?? filePath, e.Message ));
   }

   if ( filePath !=null )
   {
      _FilePath_ = filePath;
      _FileFullPath_ = fileFullPath;
   }
   _CurrentElement_ = SetCurentElementPrepareValueCollection( document.DocumentElement );
   _NamespaceManager_ = namespaceManager;
   _Document_ = document;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HXmlConfigurationBase
//**************************************************************************************************

} // CommonHelpers
