using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Antmicro.Renode.Core;
using Antmicro.Renode.Debugging;
using Antmicro.Renode.Exceptions;
using Antmicro.Renode.Hooks;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Peripherals.CPU;
using Antmicro.Renode.Peripherals.Timers;
using Antmicro.Renode.Peripherals.CPU.Disassembler;
using Antmicro.Renode.Peripherals.CPU.Registers;
using Antmicro.Renode.Utilities;
using Antmicro.Renode.Time;
using Antmicro.Renode.Utilities.Binding;

namespace Antmicro.Renode.Peripherals.MpactPeripheral {

				[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
				public delegate Int32 FuncInt32Int32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32(Int32 param0, Int32 param1,
			FuncInt32UInt64IntPtrInt32 param2, FuncInt32UInt64IntPtrInt32 param3);

	public class MpactCheriotPeripheral : IKnownSize, IBytePeripheral, IWordPeripheral, IDoubleWordPeripheral, IQuadWordPeripheral, IMultibyteWritePeripheral, IDisposable {

		public MpactCheriotPeripheral(IMachine machine, long size, int id) {
			if (size == 0) throw new ConstructionException("Memory size cannot be 0");
			this.machine = machine;
			this.size = size;
			this.id = id;
			cpuLibraryRegistered = false;
			error_ptr = Marshal.AllocHGlobal(4);
			value_ptr = Marshal.AllocHGlobal(8);
			string_ptr = Marshal.AllocHGlobal(maxStringLen);
		}

		public string CpuLibraryPath {
			get {
				return cpuLibraryPath;
			}
			set {
				if (!String.IsNullOrWhiteSpace(value)) {
					if (cpuLibraryRegistered) {
						this.WarningLog("cpu library already registerd and " +
														"should not be updated again.");
						return;
					}
					cpuLibraryPath = value;
					try {
						binder = new NativeBinder(this, cpuLibraryPath);
					} catch (System.Exception e) {
						LogAndThrowRE("Failed to load CPU library: " + e.Message);
					}
					cpuLibraryRegistered = true;
				} else {
					return;
				}
			}
		}

		public void Start() {
			if (!cpuLibraryRegistered) {
				LogAndThrowRE("Failed to register cpu library");
				return;
			}
			this.Log(LogLevel.Noisy, "Start simulator with id {0}", id);
			mpact_id = connect_with_sysbus(id, maxStringLen, null, null);
			if (mpact_id < 0) {
				LogAndThrowRE("Failed to create simulator instance");
				return;
			}
		}

		public void Reset() {}
		public void Dispose() {}

		public void WriteByte(long address, byte value) {
			var data8 = new byte[1];
			data8[0] = (byte) value;
			Marshal.Copy(data8, 0, value_ptr, 1);
			write_memory(mpact_id, (UInt64) address, value_ptr, 1);
		}

		public byte ReadByte(long address) {
			var data8 = new byte[1];
			read_memory(mpact_id, (UInt64) address, value_ptr, 1);
			Marshal.Copy(value_ptr, data8, 0, 1);
			return (byte) data8[0];
		}

		public void WriteWord(long address, ushort value) {
			var data16 = new Int16[1];
			data16[0] = (Int16) value;
			Marshal.Copy(data16, 0, value_ptr, 1);
			write_memory(mpact_id, (UInt64) address, value_ptr, 2);
		}

		public ushort ReadWord(long address) {
			var data16 = new Int16[1];
			read_memory(mpact_id, (UInt64) address, value_ptr, 2);
			Marshal.Copy(value_ptr, data16, 0, 1);
			return (ushort) data16[0];
		}

		public void WriteDoubleWord(long address, uint value) {
			var data32 = new Int32[1];
			data32[0] = (Int32) value;
			Marshal.Copy(data32, 0, value_ptr, 1);
			write_memory(mpact_id, (UInt64) address, value_ptr, 4);
		}

		public uint ReadDoubleWord(long address) {
			var data32 = new Int32[1];
			read_memory(mpact_id, (UInt64) address, value_ptr, 4);
			Marshal.Copy(value_ptr, data32, 0, 1);
			return (uint) data32[0];
		}

		public void WriteQuadWord(long address, ulong value) {
			var data64 = new Int64[1];
			data64[0] = (Int64) value;
			Marshal.Copy(data64, 0, value_ptr, 1);
			write_memory(mpact_id, (UInt64) address, value_ptr, 8);
		}

		public ulong ReadQuadWord(long address) {
			var data64 = new Int64[1];
			read_memory(mpact_id, (UInt64) address, value_ptr, 8);
			Marshal.Copy(value_ptr, data64, 0, 1);
			return (ulong) data64[0];
		}

		public byte[] ReadBytes(long offset, int count, ICPU context = null) {
			var bytes = new byte[count];
			var byte_array_ptr = Marshal.AllocHGlobal(count);
			read_memory(mpact_id, (UInt64) offset, byte_array_ptr, count);
			Marshal.Copy(value_ptr, bytes, 0, count);
			Marshal.FreeHGlobal(byte_array_ptr);
			return bytes;
		}

		public void WriteBytes(long offset, byte[] array, int startingIndex, int count, ICPU context = null) {
			var byte_array_ptr = Marshal.AllocHGlobal(count);
			Marshal.Copy(array, startingIndex, byte_array_ptr, count);
			write_memory(mpact_id, (UInt64) offset, byte_array_ptr, count);
			Marshal.FreeHGlobal(byte_array_ptr);
		}

		public long Size { get { return size;} }
		private Int32 mpact_id;
		private Int32 id {get; set;}
		private long size;
		private NativeBinder binder;
		private string cpuLibraryPath;
		private bool cpuLibraryRegistered;
		private IMachine machine;
		private readonly Int32 maxStringLen = 32;
		private IntPtr value_ptr {get; set;}
		private IntPtr error_ptr {get; set;}
		private IntPtr string_ptr {get; set;}

		private void LogAndThrowRE(string info) {
			this.Log(LogLevel.Error, info);
			throw new RecoverableException(info);
		}

	#pragma warning disable 649
		[Import(UseExceptionWrapper = false)]
		private FuncInt32Int32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32 connect_with_sysbus; // (Int32 id, Int32 callback(Uint64, IntPtr, Int32), Int32 callback(Uint64, IntPtr, Int32));
		[Import(UseExceptionWrapper = false)]
		private FuncInt32Int32UInt64IntPtrInt32 read_memory; // (Int32 id, UInt64 address, IntPtr buffer, Int32 size);
		[Import(UseExceptionWrapper = false)]
		private FuncInt32Int32UInt64IntPtrInt32 write_memory; // (Int32 id, UInt64 address, IntPtr buffer, Int32 size);
	}

}  // namespace Antmicro.Renode.Peripherals.MpactPeripheral
