package scsi

// Written against SBC-4
// Contains SCSI block device specific commands.

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"math"
)

// ReadDefectDataLBA reads the primary (manufacturer) and/or grown defect list
// in LBA format. This is commonly used on SSDs and generally returns an error
// on spinning drives.
func (d *Device) ReadDefectDataLBA(plist, glist bool) ([]uint64, error) {
	data := make([]byte, 4096)
	var req [8]byte
	if plist {
		req[1] |= 1 << 4
	}
	if glist {
		req[1] |= 1 << 3
	}
	defectListFormat := 0b011
	req[1] |= byte(defectListFormat)
	binary.BigEndian.PutUint16(req[6:8], uint16(len(data)))
	if err := d.RawCommand(&CommandDataBuffer{
		OperationCode:         ReadDefectDataOp,
		Request:               req[:],
		Data:                  data,
		DataTransferDirection: DataTransferFromDevice,
	}); err != nil {
		var fixedErr *FixedError
		if errors.As(err, &fixedErr) && fixedErr.SenseKey == RecoveredError && fixedErr.AdditionalSenseCode == DefectListNotFound {
			return nil, fmt.Errorf("error during LOG SENSE: unsupported defect list format, device returned %03bb", data[1]&0b111)
		}
		return nil, fmt.Errorf("error during LOG SENSE: %w", err)
	}
	if data[1]&0b111 != byte(defectListFormat) {
		return nil, fmt.Errorf("device returned wrong defect list format, requested %03bb, got %03bb", defectListFormat, data[1]&0b111)
	}
	defectListLength := binary.BigEndian.Uint16(data[2:4])
	if defectListLength%8 != 0 {
		return nil, errors.New("returned defect list not divisible by array item size")
	}
	if len(data) < int(defectListLength)+4 {
		return nil, errors.New("returned defect list longer than buffer")
	}
	res := make([]uint64, defectListLength/8)
	if err := binary.Read(bytes.NewReader(data[4:]), binary.BigEndian, &res); err != nil {
		panic(err)
	}
	return res, nil
}

const (
	// AllSectors is a magic sector number indicating that it applies to all
	// sectors on the track.
	AllSectors = math.MaxUint16
)

// PhysicalSectorFormatAddress represents a physical sector (or the the whole
// track if SectorNumber == AllSectors) on a spinning hard drive.
type PhysicalSectorFormatAddress struct {
	CylinderNumber              uint32
	HeadNumber                  uint8
	SectorNumber                uint32
	MultiAddressDescriptorStart bool
}

func parseExtendedPhysicalSectorFormatAddress(buf []byte) (p PhysicalSectorFormatAddress) {
	p.CylinderNumber = uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])
	p.HeadNumber = buf[3]
	p.MultiAddressDescriptorStart = buf[4]&(1<<7) != 0
	p.SectorNumber = uint32(buf[4]&0b1111)<<24 | uint32(buf[5])<<16 | uint32(buf[6])<<8 | uint32(buf[7])
	return
}

func parsePhysicalSectorFormatAddress(buf []byte) (p PhysicalSectorFormatAddress) {
	p.CylinderNumber = uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])
	p.HeadNumber = buf[3]
	p.SectorNumber = binary.BigEndian.Uint32(buf[4:8])
	return
}

// ReadDefectDataPhysical reads the primary (manufacturer) and/or grown defect
// list in physical format.
// This is only defined for spinning drives, returning an error on SSDs.
func (d *Device) ReadDefectDataPhysical(plist, glist bool) ([]PhysicalSectorFormatAddress, error) {
	data := make([]byte, 4096)
	var req [8]byte
	if plist {
		req[1] |= 1 << 4
	}
	if glist {
		req[1] |= 1 << 3
	}
	defectListFormat := 0b101
	req[1] |= byte(defectListFormat)
	binary.BigEndian.PutUint16(req[6:8], uint16(len(data)))
	if err := d.RawCommand(&CommandDataBuffer{
		OperationCode:         ReadDefectDataOp,
		Request:               req[:],
		Data:                  data,
		DataTransferDirection: DataTransferFromDevice,
	}); err != nil {
		var fixedErr *FixedError
		if errors.As(err, &fixedErr) && fixedErr.SenseKey == RecoveredError && fixedErr.AdditionalSenseCode == DefectListNotFound {
			return nil, fmt.Errorf("error during LOG SENSE: unsupported defect list format, device returned %03bb", data[1]&0b111)
		}
		return nil, fmt.Errorf("error during LOG SENSE: %w", err)
	}
	if data[1]&0b111 != byte(defectListFormat) {
		return nil, fmt.Errorf("device returned wrong defect list format, requested %03bb, got %03bb", defectListFormat, data[1]&0b111)
	}
	defectListLength := binary.BigEndian.Uint16(data[2:4])
	if defectListLength%8 != 0 {
		return nil, errors.New("returned defect list not divisible by array item size")
	}
	if len(data) < int(defectListLength)+4 {
		return nil, errors.New("returned defect list longer than buffer")
	}
	res := make([]PhysicalSectorFormatAddress, defectListLength/8)
	data = data[4:]
	for i := 0; i < int(defectListLength)/8; i++ {
		res[i] = parsePhysicalSectorFormatAddress(data[i*8 : (i+1)*8])
	}
	return res, nil
}

type SolidStateMediaHealth struct {
	// PercentageUsedEnduranceIndicator is a value which represents a
	// vendor-specific wear estimate of the solid state medium.
	// A new device starts at 0, at 100 the device is considered end-of-life.
	// Values up to 255 are possible.
	PercentageUsedEnduranceIndicator uint8
}

// SolidStateMediaHealth reports parameters about the health of the solid-state
// media of a SCSI block device.
func (d *Device) SolidStateMediaHealth() (*SolidStateMediaHealth, error) {
	raw, err := d.LogSenseParameters(LogSenseRequest{PageCode: 0x11})
	if err != nil {
		return nil, err
	}
	if len(raw[0x1]) == 0 {
		return nil, errors.New("mandatory parameter 0001h missing")
	}
	param1 := raw[0x01][0]
	if len(param1.Data) < 4 {
		return nil, errors.New("parameter 0001h too short")
	}
	return &SolidStateMediaHealth{
		PercentageUsedEnduranceIndicator: param1.Data[3],
	}, nil
}
