// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

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
}
