// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace StatsViewer
{
  /// <summary>
  /// The stats table shared memory segment contains this
  /// header structure.
  /// </summary>
  [StructLayout(LayoutKind.Sequential)]
  internal struct StatsFileHeader {
    public int version;
    public int size;
    public int max_counters;
    public int max_threads;
  };

  /// <summary>
  /// An entry in the StatsTable.
  /// </summary>
  class StatsTableEntry {
    public StatsTableEntry(int id, string name, StatsTable table) {
      id_ = id;
      name_ = name;
      table_ = table;
    }

    /// <summary>
    /// The unique id for this entry
    /// </summary>
    public int id { get { return id_; } }

    /// <summary>
    /// The name for this entry.
    /// </summary>
    public string name { get { return name_; } }

    /// <summary>
    /// The value of this entry now.  
    /// </summary>
    public int GetValue(int filter_pid) {
      return table_.GetValue(id_, filter_pid);
    }

    private int id_;
    private string name_;
    private StatsTable table_;
  }

  // An interface for StatsCounters
  interface IStatsCounter {
    // The name of the counter
    string name { get; }
  }

  // A counter.
  class StatsCounter : IStatsCounter {
    public StatsCounter(StatsTableEntry entry) {
      entry_ = entry;
    }

    public string name { 
      get {
        return entry_.name; 
      } 
    }

    public int GetValue(int filter_pid) {
      return entry_.GetValue(filter_pid);
    }

    private StatsTableEntry entry_;
  }

  // A timer.
  class StatsTimer : IStatsCounter {
    public StatsTimer(StatsTableEntry entry)
    {
      entry_ = entry;
    }

    public string name { 
      get { 
        return entry_.name; 
      } 
    }

    public int GetValue(int filter_pid) {
      return entry_.GetValue(filter_pid);
    }

    private StatsTableEntry entry_;
  }

  // A rate.
  class StatsCounterRate : IStatsCounter
  {
    public StatsCounterRate(StatsCounter counter, StatsTimer timer) {
      counter_ = counter;
      timer_ = timer;
    }

    public string name { get { return counter_.name; } }

    public int GetCount(int filter_pid) { 
      return counter_.GetValue(filter_pid);
    }

    public int GetTime(int filter_pid) {
      return timer_.GetValue(filter_pid);
    }

    private StatsCounter counter_;
    private StatsTimer timer_;
  }

  /// <summary>
  /// This is a C# reader for the chrome stats_table.
  /// </summary>
  class StatsTable {
    internal const int kMaxThreadNameLength = 32;
    internal const int kMaxCounterNameLength = 32;

    /// <summary>
    /// Open a StatsTable
    /// </summary>
    public StatsTable() {
    }

    #region Public Properties
    /// <summary>
    /// Get access to the counters in the table.
    /// </summary>
    public StatsTableCounters Counters() {
      return new StatsTableCounters(this);
    }

    /// <summary>
    /// Get access to the processes in the table
    /// </summary>
    public ICollection Processes {
      get {
        return new StatsTableProcesses(this);
      }
    }
    #endregion

    #region Internal Properties
    // 
    // The internal methods are accessible to the enumerators
    // and helper classes below.
    //
    
    /// <summary>
    /// Access to the table header
    /// </summary>
    internal StatsFileHeader Header {
      get { return header_; }
    }

    /// <summary>
    /// Get the offset of the ThreadName table
    /// </summary>
    internal long ThreadNamesOffset {
      get {
        return memory_.ToInt64() + Marshal.SizeOf(typeof(StatsFileHeader));
      }
    }

    /// <summary>
    /// Get the offset of the PIDs table
    /// </summary>
    internal long PidsOffset {
      get {
        long offset = ThreadNamesOffset;
        // Thread names table
        offset += AlignedSize(header_.max_threads * kMaxThreadNameLength * 2);
        // Thread TID table
        offset += AlignedSize(header_.max_threads * 
          Marshal.SizeOf(typeof(int)));
        return offset;
      }
    }

    /// <summary>
    /// Get the offset of the CounterName table
    /// </summary>
    internal long CounterNamesOffset {
      get {
        long offset = PidsOffset;
        // Thread PID table
        offset += AlignedSize(header_.max_threads * 
          Marshal.SizeOf(typeof(int)));
        return offset;
      }
    }

    /// <summary>
    /// Get the offset of the Data table
    /// </summary>
    internal long DataOffset {
      get {
        long offset = CounterNamesOffset;
        // Counter names table
        offset += AlignedSize(header_.max_counters * 
          kMaxCounterNameLength * 2);
        return offset;
      }
    }
    #endregion

    #region Public Methods
    /// <summary>
    /// Opens the memory map
    /// </summary>
    /// <returns></returns>
    /// <param name="name">The name of the file to open</param>
    public bool Open(string name) {
      map_handle_ = 
        Win32.OpenFileMapping((int)Win32.MapAccess.FILE_MAP_WRITE, false, 
                              name);
      if (map_handle_ == IntPtr.Zero)
        return false;

      memory_ = 
        Win32.MapViewOfFile(map_handle_, (int)Win32.MapAccess.FILE_MAP_WRITE, 
                            0,0, 0);
      if (memory_ == IntPtr.Zero) {
        Win32.CloseHandle(map_handle_);
        return false;
      }

      header_ = (StatsFileHeader)Marshal.PtrToStructure(memory_, header_.GetType());
      return true;
    }

    /// <summary>
    /// Close the mapped file.
    /// </summary>
    public void Close() {
      Win32.UnmapViewOfFile(memory_);
      Win32.CloseHandle(map_handle_);
    }

    /// <summary>
    /// Zero out the stats file.
    /// </summary>
    public void Zero() {
      long offset = DataOffset;
      for (int threads = 0; threads < header_.max_threads; threads++) {
        for (int counters = 0; counters < header_.max_counters; counters++) {
          Marshal.WriteInt32((IntPtr) offset, 0);
          offset += Marshal.SizeOf(typeof(int));
        }
      }
    }

    /// <summary>
    /// Get the value for a StatsCounterEntry now.
    /// </summary>
    /// <returns></returns>
    /// <param name="filter_pid">If a specific PID is being queried, filter to this PID.  0 means use all data.</param>
    /// <param name="id">The id of the CounterEntry to get the value for.</param>
    public int GetValue(int id, int filter_pid) {
      long pid_offset = PidsOffset;
      long data_offset = DataOffset;
      data_offset += id * (Header.max_threads * 
        Marshal.SizeOf(typeof(int)));
      int rv = 0;
      for (int cols = 0; cols < Header.max_threads; cols++)
      {
        int pid = Marshal.ReadInt32((IntPtr)pid_offset);
        if (filter_pid == 0 || filter_pid == pid)
        {
          rv += Marshal.ReadInt32((IntPtr)data_offset);
        }
        data_offset += Marshal.SizeOf(typeof(int));
        pid_offset += Marshal.SizeOf(typeof(int));
      }
      return rv;
    }
    #endregion

    #region Private Methods
    /// <summary>
    /// Align to 4-byte boundaries
    /// </summary>
    /// <param name="size"></param>
    /// <returns></returns>
    private long AlignedSize(long size) {
      Debug.Assert(sizeof(int) == 4);
      return size + (sizeof(int) - (size % sizeof(int))) % sizeof(int);
    }
    #endregion

    #region Private Members
    private IntPtr memory_;
    private IntPtr map_handle_;
    private StatsFileHeader header_;
    #endregion
  }

  /// <summary>
  /// Enumerable list of Counters in the StatsTable
  /// </summary>
  class StatsTableCounters : ICollection {
    /// <summary>
    /// Create the list of counters
    /// </summary>
    /// <param name="table"></param>
    /// pid</param>
    public StatsTableCounters(StatsTable table) {
      table_ = table;
      counter_hi_water_mark_ = -1;
      counters_ = new List<IStatsCounter>();
      FindCounters();
    }

    /// <summary>
    /// Scans the table for new entries.
    /// </summary>
    public void Update() {
      FindCounters();
    }

    #region IEnumerable Members
    public IEnumerator GetEnumerator() {
      return counters_.GetEnumerator();
    }
    #endregion

    #region ICollection Members
    public void CopyTo(Array array, int index) {
      throw new Exception("The method or operation is not implemented.");
    }

    public int Count {
      get {
        return counters_.Count;
      }
    }

    public bool IsSynchronized {
      get { 
        throw new Exception("The method or operation is not implemented."); 
      }
    }

    public object SyncRoot {
      get { 
        throw new Exception("The method or operation is not implemented."); 
      }
    }
    #endregion

    #region Private Methods
    /// <summary>
    /// Create a counter based on an entry
    /// </summary>
    /// <param name="id"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    private IStatsCounter NameToCounter(int id, string name)
    {
      IStatsCounter rv = null;

      // check if the name has a type encoded
      if (name.Length > 2 && name[1] == ':')
      {
        StatsTableEntry entry = new StatsTableEntry(id, name.Substring(2), table_);
        switch (name[0])
        {
          case 't':
            rv = new StatsTimer(entry);
            break;
          case 'c':
            rv = new StatsCounter(entry);
            break;
        }
      }
      else
      {
        StatsTableEntry entry = new StatsTableEntry(id, name, table_);
        rv = new StatsCounter(entry);
      }

      return rv;
    }

    // If we have two StatsTableEntries with the same name, 
    // attempt to upgrade them to a higher level type.  
    // Example:  A counter + a timer == a rate!
    private void UpgradeCounter(IStatsCounter old_counter, IStatsCounter counter)
    {
      if (old_counter is StatsCounter && counter is StatsTimer)
      {
        StatsCounterRate rate = new StatsCounterRate(old_counter as StatsCounter,
                                          counter as StatsTimer);
        counters_.Remove(old_counter);
        counters_.Add(rate);
      }
      else if (old_counter is StatsTimer && counter is StatsCounter)
      {
        StatsCounterRate rate = new StatsCounterRate(counter as StatsCounter,
                                         old_counter as StatsTimer);
        counters_.Remove(old_counter);
        counters_.Add(rate);
      }
    }

    /// <summary>
    /// Find the counters in the table and insert into the counters_
    /// hash table.
    /// </summary>
    private void FindCounters()
    {
      Debug.Assert(table_.Header.max_counters > 0);

      int index = counter_hi_water_mark_;

      do
      {
        // Find an entry in the table.
        index++;
        long offset = table_.CounterNamesOffset +
          (index * StatsTable.kMaxCounterNameLength * 2);
        string name = Marshal.PtrToStringUni((IntPtr)offset);
        if (name.Length == 0)
          continue;

        // Record that we've already looked at this StatsTableEntry.
        counter_hi_water_mark_ = index;

        IStatsCounter counter = NameToCounter(index, name);

        if (counter != null)
        {
          IStatsCounter old_counter = FindExistingCounter(counter.name);
          if (old_counter != null)
            UpgradeCounter(old_counter, counter);
          else
            counters_.Add(counter);
        }
      } while (index < table_.Header.max_counters - 1);
    }

    /// <summary>
    /// Find an existing counter in our table
    /// </summary>
    /// <param name="name"></param>
    private IStatsCounter FindExistingCounter(string name) {
      foreach (IStatsCounter ctr in counters_)
      {
        if (ctr.name == name)
          return ctr;
      }
      return null;
    }
    #endregion

    #region Private Members
    private StatsTable table_;
    private List<IStatsCounter> counters_;
    // Highest index of counters processed.
    private int counter_hi_water_mark_;
    #endregion
  }

  /// <summary>
  /// A collection of processes
  /// </summary>
  class StatsTableProcesses : ICollection
  {
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="table"></param>
    public StatsTableProcesses(StatsTable table) {
      table_ = table;
      pids_ = new List<int>();
      Initialize();
    }

    #region ICollection Members
    public void CopyTo(Array array, int index) {
      throw new Exception("The method or operation is not implemented.");
    }

    public int Count {
      get {
        return pids_.Count;
      }
    }

    public bool IsSynchronized {
      get {
        throw new Exception("The method or operation is not implemented."); 
      }
    }

    public object SyncRoot {
      get { 
        throw new Exception("The method or operation is not implemented."); 
      }
    }
    #endregion

    #region IEnumerable Members
    public IEnumerator GetEnumerator() {
      return pids_.GetEnumerator();
    }
    #endregion

    /// <summary>
    /// Initialize the pid list.
    /// </summary>
    private void Initialize() {
      long offset = table_.ThreadNamesOffset;

      for (int index = 0; index < table_.Header.max_threads; index++) {
        string thread_name = Marshal.PtrToStringUni((IntPtr)offset);
        if (thread_name.Length > 0) {
          long pidOffset = table_.PidsOffset + index * 
            Marshal.SizeOf(typeof(int));
          int pid = Marshal.ReadInt32((IntPtr)pidOffset);
          if (!pids_.Contains(pid))
            pids_.Add(pid);
        }
        offset += StatsTable.kMaxThreadNameLength * 2;
      }
    }

    #region Private Members
    private StatsTable table_;
    private List<int> pids_;
    #endregion
  }
}
