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


using CPU = Indy.IL2CPU.Assembler;
using CPUx86 = Indy.IL2CPU.Assembler.X86;
using System.Reflection;

namespace Indy.IL2CPU.IL.X86.Native {
	public class NativePutCharOp: IL.X86.Op {
		public MethodInformation MethodInformation;
		public NativePutCharOp(ILReader aReader, MethodInformation aMethodInfo)
			: base(aReader, aMethodInfo) {
			MethodInformation = aMethodInfo;
		}

		private void AssembleOp(IL.Op aOp) {
			aOp.Assembler = this.Assembler;
			aOp.Assemble();
		}
		private unsafe static void DoPutChar(int aLine, int aPos, byte aChar) {
			byte* xScreenPtr = (byte*)0xB8000;
			xScreenPtr += (aPos + (aLine * 80)) * 2;
			*xScreenPtr = aChar;
			xScreenPtr += 1;
			*xScreenPtr = 7;
		}

		protected void PassCall(MethodBase aMethod) {
			for (int i = 0; i < MethodInformation.Arguments.Length; i++) {
				Ldarg(Assembler, MethodInformation.Arguments[i]);
			}
			DoQueueMethod(aMethod);
			new Indy.IL2CPU.Assembler.X86.Call(CPU.Label.GenerateLabelName(aMethod));
			MethodInfo xMethodInfo = aMethod as MethodInfo;
			if (xMethodInfo != null) {
				if (!xMethodInfo.ReturnType.FullName.StartsWith("System.Void")) {
					new Indy.IL2CPU.Assembler.X86.Pushd("eax");
				}
			}
		}
		public override void DoAssemble() {
			Type xType = typeof(NativePutCharOp);
			PassCall(xType.GetMethod("DoPutChar"));
			//(int aLine, int aPos, char aChar)
			//			Ldarg(mAssembler, MethodInformation.Arguments[0].VirtualAddress);
			//			Pushd("80");
			//			Multiply();
			//			Ldarg(mAssembler, MethodInformation.Arguments[1].VirtualAddress);
			//			Add();
			//			Pushd("2");
			//			Multiply();
			//			Pushd("0B8000h");
			//			Add();
			//			Ldarg(mAssembler, MethodInformation.Arguments[2].VirtualAddress);
			//			Pop("eax"); // character
			//			Assembler.Add(new IL2CPU.Assembler.X86.And("eax", "0FFFFFFFFh"));
			//			Pop("ecx");
			//			Assembler.Add(new CPUx86.Move("byte [ecx]", "al"));
			//			Assembler.Add(new CPUx86.Add("ecx", "1"));
			//			Assembler.Add(new CPUx86.Move("byte [ecx]", "7"));
		}
	}
}