package disk

import "fmt"

/*
	2MG format loader...
*/

const PREAMBLE_2MG_SIZE = 0x40

var MAGIC_2MG = []byte{byte('2'), byte('I'), byte('M'), byte('G')}

type Header2MG struct {
	Data [64]byte
}

func (h *Header2MG) SetData(data []byte) {
	for i, v := range data {
		if i < 64 {
			h.Data[i] = v
		}
	}
}

func (h *Header2MG) GetID() string {
	return string(h.Data[0x00:0x04])
}

func (h *Header2MG) GetCreatorID() string {
	return string(h.Data[0x04:0x08])
}

func (h *Header2MG) GetHeaderSize() int {
	return int(h.Data[0x08]) + 256*int(h.Data[0x09])
}

func (h *Header2MG) GetVersion() int {
	return int(h.Data[0x0A]) + 256*int(h.Data[0x0B])
}

func (h *Header2MG) GetImageFormat() int {
	return int(h.Data[0x0C]) + 256*int(h.Data[0x0D]) + 65336*int(h.Data[0x0E]) + 16777216*int(h.Data[0x0F])
}

func (h *Header2MG) GetDOSFlags() int {
	return int(h.Data[0x10]) + 256*int(h.Data[0x11]) + 65336*int(h.Data[0x12]) + 16777216*int(h.Data[0x13])
}

func (h *Header2MG) GetProDOSBlocks() int {
	return int(h.Data[0x14]) + 256*int(h.Data[0x15]) + 65336*int(h.Data[0x16]) + 16777216*int(h.Data[0x17])
}

func (h *Header2MG) GetDiskDataStart() int {
	return int(h.Data[0x18]) + 256*int(h.Data[0x19]) + 65336*int(h.Data[0x1A]) + 16777216*int(h.Data[0x1B])
}

func (h *Header2MG) GetDiskDataLength() int {
	return int(h.Data[0x1C]) + 256*int(h.Data[0x1D]) + 65336*int(h.Data[0x1E]) + 16777216*int(h.Data[0x1F])
}

func (dsk *DSKWrapper) Is2MG() (bool, DiskFormat, SectorOrder, *DSKWrapper) {

	h := &Header2MG{}
	h.SetData(dsk.Data[:0x40])

	if h.GetID() != "2IMG" {
		return false, GetDiskFormat(DF_NONE), SectorOrderDOS33, nil
	}

	fmt.Println("Disk has 2MG Magic")
	fmt.Printf("Block count %d\n", h.GetProDOSBlocks())

	start := h.GetDiskDataStart()
	size := h.GetDiskDataLength()

	if size < len(dsk.Data)-start {
		size = len(dsk.Data) - start
	}

	if size != STD_DISK_BYTES && size != PRODOS_800KB_DISK_BYTES && size != PRODOS_400KB_DISK_BYTES {
		fmt.Printf("Bad size %d bytes @ start %d\n", size, start)
		return false, GetDiskFormat(DF_NONE), SectorOrderDOS33, nil
	}

	data := dsk.Data[start : start+size]
	format := h.GetImageFormat()
	switch format {
	case 0x00: /* DOS sector order */
		zdsk, _ := NewDSKWrapperBin(dsk.Nibbles, data, dsk.Filename)
		return true, GetDiskFormat(DF_DOS_SECTORS_16), SectorOrderDOS33, zdsk
	case 0x01: /* ProDOS sector order */
		zdsk, _ := NewDSKWrapperBin(dsk.Nibbles, data, dsk.Filename)

		if h.GetProDOSBlocks() == 1600 {
			return true, GetDiskFormat(DF_PRODOS_800KB), SectorOrderProDOSLinear, zdsk
		} else if h.GetProDOSBlocks() == 800 {
			return true, GetDiskFormat(DF_PRODOS_400KB), SectorOrderProDOSLinear, zdsk
		} else {
			return true, GetPDDiskFormat(DF_PRODOS_CUSTOM, h.GetProDOSBlocks()), SectorOrderProDOSLinear, zdsk
		}

	}

	return false, GetDiskFormat(DF_NONE), SectorOrderDOS33, nil

}