//-----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All Rights Reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
//^ using Microsoft.Contracts;
namespace Microsoft.Cci.Ast {
  /// <summary>
  /// Represents a .NET assembly.
  /// </summary>
  public abstract class Assembly : Module, IAssembly {
    /// <summary>
    /// Allocates an object that represents a .NET assembly.
    /// </summary>
    /// <param name="name">The name of the unit.</param>
    /// <param name="location">An indication of the location where the unit is or will be stored. This need not be a file system path and may be empty. 
    /// The interpretation depends on the IMetadataHost instance used to resolve references to this unit.</param>
    /// <param name="moduleName">The name of the module containing the assembly manifest. This can be different from the name of the assembly itself.</param>
    /// <param name="assemblyReferences">A list of the assemblies that are referenced by this module.</param>
    /// <param name="moduleReferences">A list of the modules that are referenced by this module.</param>
    /// <param name="resources">A list of named byte sequences persisted with the assembly and used during execution, typically via .NET Framework helper classes.</param>
    /// <param name="files">
    /// A list of the files that constitute the assembly. These are not the source language files that may have been
    /// used to compile the assembly, but the files that contain constituent modules of a multi-module assembly as well
    /// as any external resources. It corresonds to the File table of the .NET assembly file format.
    /// </param>
    protected Assembly(IName name, string location, IName moduleName, IEnumerable<IAssemblyReference> assemblyReferences, IEnumerable<IModuleReference> moduleReferences,
      IEnumerable<IResourceReference> resources, IEnumerable<IFileReference> files)
      : base(name, location, Dummy.Assembly, assemblyReferences, moduleReferences) {
      this.moduleName = moduleName;
      this.resources = resources;
      this.files = files;
    }
    /// <summary>
    /// A list of aliases for the root namespace of the referenced assembly.
    /// </summary>
    public IEnumerable<IName> Aliases {
      get { return Enumerable<IName>.Empty; }
    }
    /// <summary>
    /// A list of objects representing persisted instances of types that extend System.Attribute. Provides an extensible way to associate metadata
    /// with this assembly.
    /// </summary>
    public IEnumerable<ICustomAttribute> AssemblyAttributes {
      get {
        if (this.assemblyAttributes == null) {
          var assemblyAttributes = this.GetAssemblyAttributes();
          assemblyAttributes.TrimExcess();
          this.assemblyAttributes = assemblyAttributes.AsReadOnly();
        }
        return this.assemblyAttributes;
      }
    }
    IEnumerable<ICustomAttribute> assemblyAttributes;
    /// <summary>
    /// The identity of the assembly.
    /// </summary>
    public AssemblyIdentity AssemblyIdentity {
      get {
        if (this.assemblyIdentity == null)
          this.assemblyIdentity = UnitHelper.GetAssemblyIdentity(this);
        return this.assemblyIdentity;
      }
    }
    AssemblyIdentity/*?*/ assemblyIdentity;
    /// <summary>
    /// The assembly that contains this module.
    /// </summary>
    public override IAssembly/*?*/ ContainingAssembly {
      get { return this; }
    }
    /// <summary>
    /// Identifies the culture associated with the assembly. Typically specified for sattelite assemblies with localized resources.
    /// Empty if not specified.
    /// </summary>
    public virtual string Culture {
      get { return string.Empty; }
    }
    /// <summary>
    /// Calls visitor.Visit(IAssembly).
    /// </summary>
    public override void Dispatch(IMetadataVisitor visitor) {
      visitor.Visit(this);
    }
    /// <summary>
    /// Calls visitor.Visit(IAssemblyReference).
    /// </summary>
    public override void DispatchAsReference(IMetadataVisitor visitor) {
      visitor.Visit((IAssemblyReference)this);
    }
    /// <summary>
    /// Public types defined in other modules making up this assembly and to which other assemblies may refer to via this assembly.
    /// </summary>
    public virtual IEnumerable<IAliasForType> ExportedTypes {
      get { return Enumerable<IAliasForType>.Empty; }
    }
    /// <summary>
    /// A list of the files that constitute the assembly. These are not the source language files that may have been
    /// used to compile the assembly, but the files that contain constituent modules of a multi-module assembly as well
    /// as any external resources. It corresonds to the File table of the .NET assembly file format.
    /// </summary>
    public IEnumerable<IFileReference> Files {
      get { return this.files; }
    }
    readonly IEnumerable<IFileReference> files;
    /// <summary>
    /// A set of bits and bit ranges representing properties of the assembly. The value of <see cref="Flags"/> can be set
    /// from source code via the AssemblyFlags assembly custom attribute. The interpretation of the property depends on the target platform.
    /// </summary>
    public virtual uint Flags {
      get { return 0; } //TODO: get from options or an attribute
    }
    /// <summary>
    /// Returns a list of custom attributes that describes this type declaration member.
    /// Typically, these will be derived from this.SourceAttributes. However, some source attributes
    /// might instead be persisted as metadata bits and other custom attributes may be synthesized
    /// from information not provided in the form of source custom attributes.
    /// The list is not trimmed to size, since an override of this method may call the base method
    /// and then add more attributes.
    /// </summary>
    protected virtual List<ICustomAttribute> GetAssemblyAttributes() {
      List<ICustomAttribute> result = new List<ICustomAttribute>();
      bool sawTypeWithExtensions = false;
      this.UnitNamespaceRoot.FillInWithAssemblyAttributes(result, ref sawTypeWithExtensions);
      if (sawTypeWithExtensions) {
        var eattr = new Microsoft.Cci.MutableCodeModel.CustomAttribute();
        eattr.Constructor = this.Compilation.ExtensionAttributeCtor;
        result.Add(eattr);
      }
      return result;
    }
    /// <summary>
    /// The encrypted SHA1 hash of the persisted form of the referenced assembly.
    /// </summary>
    public IEnumerable<byte> HashValue {
      get { return Enumerable<byte>.Empty; }
    }
    /// <summary>
    /// True if the implementation of the referenced assembly used at runtime is not expected to match the version seen at compile time.
    /// </summary>
    public virtual bool IsRetargetable {
      get { return false; } //TODO: get from options or an attribute
    }
    /// <summary>
    /// The kind of metadata stored in the module. For example whether the module is an executable or a manifest resource file.
    /// </summary>
    public override ModuleKind Kind {
      get { return this.EntryPoint.ResolvedMethod is Dummy ? ModuleKind.DynamicallyLinkedLibrary : ModuleKind.ConsoleApplication; } //TODO: obtain it from the compiler options
    }
    /// <summary>
    /// A list of the modules that constitute the assembly.
    /// </summary>
    public IEnumerable<IModule> MemberModules {
      get { return Enumerable<IModule>.Empty; }
    }
    /// <summary>
    /// The identity of the module.
    /// </summary>
    public override ModuleIdentity ModuleIdentity {
      get { return this.AssemblyIdentity; }
    }
    /// <summary>
    /// The name of the module containing the assembly manifest. This can be different from the name of the assembly itself.
    /// </summary>
    public override IName ModuleName {
      get { return this.moduleName; }
    }
    readonly IName moduleName;
    /// <summary>
    /// The public part of the key used to encrypt the SHA1 hash over the persisted form of this assembly . Empty if not specified.
    /// This value is used by the loader to decrypt HashValue which it then compares with a freshly computed hash value to verify the
    /// integrity of the assembly.
    /// </summary>
    public virtual IEnumerable<byte> PublicKey {
      get { return Enumerable<byte>.Empty; } //TODO: get this from an option or attribute
    }
    /// <summary>
    /// The hashed 8 bytes of the public key called public key token of the referenced assembly. This is non empty of the referenced assembly is strongly signed.
    /// </summary>
    public IEnumerable<byte> PublicKeyToken {
      get { return UnitHelper.ComputePublicKeyToken(this.PublicKey); }
    }
    /// <summary>
    /// A list of named byte sequences persisted with the assembly and used during execution, typically via .NET Framework helper classes.
    /// </summary>
    public IEnumerable<IResourceReference> Resources {
      get { return this.resources; }
    }
    readonly IEnumerable<IResourceReference> resources;
    /// <summary>
    /// A list of objects representing persisted instances of pairs of security actions and sets of security permissions.
    /// These apply by default to every method reachable from the module.
    /// </summary>
    public virtual IEnumerable<ISecurityAttribute> SecurityAttributes {
      get { return Enumerable<ISecurityAttribute>.Empty; } //TODO: compute this
    }
    /// <summary>
    /// The version of the assembly.
    /// </summary>
    public virtual Version Version {
      get { return new System.Version(0, 0, 0, 0); } //TODO: obtain from compiler options or custom attributes
    }
    #region IAssemblyReference Members
    IAssembly IAssemblyReference.ResolvedAssembly {
      get { return this; }
    }
    AssemblyIdentity IAssemblyReference.UnifiedAssemblyIdentity {
      get { return this.AssemblyIdentity; }
    }
    bool IAssemblyReference.ContainsForeignTypes {
      get { return false; }
    }
    #endregion
    #region IModuleReference Members
    IAssemblyReference/*?*/ IModuleReference.ContainingAssembly {
      get { return this; }
    }
    #endregion
  }
  /// <summary>
  /// A reference to a .NET assembly.
  /// </summary>
  public class ResolvedAssemblyReference : ResolvedModuleReference, IAssemblyReference {
    /// <summary>
    /// Allocates a reference to a .NET assembly.
    /// </summary>
    /// <param name="referencedAssembly">The assembly to reference.</param>
    public ResolvedAssemblyReference(IAssembly referencedAssembly)
      : base(referencedAssembly) {
      this.aliases = Enumerable<IName>.Empty;
    }
    /// <summary>
    /// A list of aliases for the root namespace of the referenced assembly.
    /// </summary>
    public IEnumerable<IName> Aliases {
      get { return this.aliases; }
    }
    IEnumerable<IName> aliases;
    /// <summary>
    /// The identity of the assembly reference.
    /// </summary>
    public AssemblyIdentity AssemblyIdentity {
      get { return this.ResolvedAssembly.AssemblyIdentity; }
    }
    /// <summary>
    /// Identifies the culture associated with the assembly reference. Typically specified for sattelite assemblies with localized resources.
    /// Empty if not specified.
    /// </summary>
    public string Culture {
      get { return this.ResolvedAssembly.Culture; }
    }
    /// <summary>
    /// Calls the visitor.Visit(IAssemblyReference) method.
    /// </summary>
    public override void Dispatch(IMetadataVisitor visitor) {
      visitor.Visit(this);
    }
    /// <summary>
    /// Calls the visitor.Visit(IAssemblyReference) method.
    /// </summary>
    public override void DispatchAsReference(IMetadataVisitor visitor) {
      visitor.Visit(this);
    }
    /// <summary>
    /// The encrypted SHA1 hash of the persisted form of the referenced assembly.
    /// </summary>
    public IEnumerable<byte> HashValue {
      get { return this.ResolvedAssembly.HashValue; }
    }
    /// <summary>
    /// True if the implementation of the referenced assembly used at runtime is not expected to match the version seen at compile time.
    /// </summary>
    public virtual bool IsRetargetable {
      get { return this.ResolvedAssembly.IsRetargetable; }
    }
    /// <summary>
    /// The public part of the key used to encrypt the SHA1 hash over the persisted form of the referenced assembly. Empty if not specified.
    /// This value is used by the loader to decrypt an encrypted hash value stored in the assembly, which it then compares with a freshly computed hash value
    /// in order to verify the integrity of the assembly.
    /// </summary>
    public IEnumerable<byte> PublicKey {
      get { return this.ResolvedAssembly.PublicKey; }
    }
    /// <summary>
    /// The hashed 8 bytes of the public key called public key token of the referenced assembly. This is non empty of the referenced assembly is strongly signed.
    /// </summary>
    public IEnumerable<byte> PublicKeyToken {


Answer:       get { return this.ResolvedAssembly.PublicKeyToken; }