using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lomont.Utils;

namespace Lomont.Binary.X86
    {
    /// <summary>
    /// Class used to pass around relevant decoding data while decoding an instruction.
    /// </summary>
    sealed public class X86DecodeContext : IMessager
        {

        /// <summary>
        /// The current instruction being decoded
        /// </summary>
        public X86Instruction Instruction { get; set; }

        /// <summary>
        /// The processor mode used when decoding.
        /// </summary>
        public X86ProcessorMode ProcessorMode { get; set; }

        /// <summary>
        /// Store a place to send and receive messages
        /// </summary>
        public Messager Messager { get; set; }

        /// <summary>
        /// The byte stream to read for data.
        /// </summary>
        public ByteStream Data { get; set; }

        /// <summary>
        /// Tables storing decoding information. One copy for all threads and objects needing them
        /// </summary>
        public X86DefinitionTables tables { get; set; }

        /// <summary>
        /// The base loading address of the image. 
        /// This is the address added to each address in the
        /// image when loaded. It comes from a PE file header.
        /// TODO - extract to a disassembly extension area, allowing more disassembly tricks
        /// </summary>
        public ulong ImageBase { get; set; }

        /// <summary>
        /// Create a decoding context for decoding an instruction.
        /// This object is reusable, meaning it can be passed into the decoder
        /// repeatedly, obtaining a new instruction each time.
        /// </summary>
        /// <param name="messager">An object to record messages</param>
        /// <param name="processorMode">A processor mode, giving decoding details.</param>
        /// <param name="data">A stream of bytes to decode.</param>
        public X86DecodeContext(Messager messager, X86ProcessorMode processorMode, ByteStream data)
            {
            Messager = messager;
            ProcessorMode = processorMode;
            Data = data;
            tables = new X86DefinitionTables(messager, processorMode); // todo - base on processor mode
            }

        #region IMessager interface

        public void OnMessage(string format, params object[] args)
            {
            if (Messager != null)
                Messager.OnMessage(format, args);
            }

        public void OnError(string format, params object[] args)
            {
            if (Messager != null)
                Messager.OnError(format, args);
            }

        public void OnWarning(string format, params object[] args)
            {
            if (Messager != null)
                Messager.OnWarning(format, args);
            }

        public void OnInfo(string format, params object[] args)
            {
            if (Messager != null)
                Messager.OnInfo(format, args);
            }
        #endregion
        }
    }
