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

package scsi

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

type LogSenseRequest struct {
	// PageCode contains the identifier of the requested page
	PageCode uint8
	// SubpageCode contains the identifier of the requested subpage
	// or the zero value if no subpage is requested.
	SubpageCode uint8
	// PageControl specifies what type of values should be returned for bounded
	// and unbounded log parameters. See also Table 156 in the standard.
	PageControl uint8
	// ParameterPointer allows requesting parameter data beginning from a
	// specific parameter code. The zero value starts from the beginning.
	ParameterPointer uint16
	// SaveParameters requests the device to save all parameters without
	// DisableUpdate set to non-volatile storage.
	SaveParameters bool
	// InitialSize is an optional hint how big the buffer for the log page
	// should be for the initial request. The zero value sets this to 4096.
	InitialSize uint16
}

// LogSenseRaw requests a raw log page. For log pages with parameters
// LogSenseParameters is better-suited.
func (d *Device) LogSenseRaw(r LogSenseRequest) ([]byte, error) {
	var bufferSize uint16 = 4096
	for {
		data := make([]byte, bufferSize)
		var req [8]byte
		if r.SaveParameters {
			req[0] = 0b1
		}
		req[1] = r.PageControl<<6 | r.PageCode
		req[2] = r.SubpageCode
		binary.BigEndian.PutUint16(req[4:6], r.ParameterPointer)
		binary.BigEndian.PutUint16(req[6:8], uint16(len(data)))
		if err := d.RawCommand(&CommandDataBuffer{
			OperationCode:         LogSenseOp,
			Request:               req[:],
			Data:                  data,
			DataTransferDirection: DataTransferFromDevice,
		}); err != nil {
			return nil, fmt.Errorf("error during LOG SENSE: %w", err)
		}
		if data[0]&0b111111 != r.PageCode {
			return nil, fmt.Errorf("requested log page %x, got %x", r.PageCode, data[1])
		}
		if data[1] != r.SubpageCode {
			return nil, fmt.Errorf("requested log subpage %x, got %x", r.SubpageCode, data[1])
		}
		pageLength := binary.BigEndian.Uint16(data[2:4])
		if pageLength > math.MaxUint16-4 {
			// Guard against uint16 overflows, this cannot be requested anyways
			return nil, fmt.Errorf("device log page is too long (%d bytes)", pageLength)
		}
		if pageLength > uint16(len(data)-4) {
			bufferSize = pageLength + 4
			continue
		}
		return data[4 : pageLength+4], nil
	}
}

// SupportedLogPages returns a map with all supported log pages.
// This can return an error if the device does not support logs at all.
func (d *Device) SupportedLogPages() (map[uint8]bool, error) {
	raw, err := d.LogSenseRaw(LogSenseRequest{PageCode: 0})
	if err != nil {
		return nil, err
	}
	res := make(map[uint8]bool)
	for _, r := range raw {
		res[r] = true
	}
	return res, nil
}

// PageAndSubpage identifies a log page uniquely.
type PageAndSubpage uint16

func NewPageAndSubpage(page, subpage uint8) PageAndSubpage {
	return PageAndSubpage(uint16(page)<<8 | uint16(subpage))
}

func (p PageAndSubpage) Page() uint8 {
	return uint8(p >> 8)
}
func (p PageAndSubpage) Subpage() uint8 {
	return uint8(p & 0xFF)
}

func (p PageAndSubpage) String() string {
	return fmt.Sprintf("Page %xh Subpage %xh", p.Page(), p.Subpage())
}

// SupportedLogPagesAndSubpages returns the list of supported pages and subpages.
// This can return an error if the device does not support logs at all.
func (d *Device) SupportedLogPagesAndSubpages() (map[PageAndSubpage]bool, error) {
	raw, err := d.LogSenseRaw(LogSenseRequest{PageCode: 0x00, SubpageCode: 0xff})
	if err != nil {
		return nil, err
	}
	res := make(map[PageAndSubpage]bool)
	for i := 0; i < len(raw)/2; i++ {
		res[NewPageAndSubpage(raw[i*2], raw[(i*2)+1])] = true
	}
	return res, nil
}

// SupportedLogSubPages returns the list of subpages supported in a log page.
func (d *Device) SupportedLogSubPages(pageCode uint8) (map[uint8]bool, error) {
	raw, err := d.LogSenseRaw(LogSenseRequest{PageCode: pageCode, SubpageCode: 0xff})
	if err != nil {
		return nil, err
	}
	res := make(map[uint8]bool)
	for _, r := range raw {
		res[r] = true
	}
	return res, nil
}

type LogParameter struct {
	// DisableUpdate indicates if the device is updating this parameter.
	// If this is true the parameter has either overflown or updating has been
	// manually disabled.
	DisableUpdate bool
	// TargetSaveDisable indicates if automatic saving of this parameter has
	// been disabled.
	TargetSaveDisable bool
	// FormatAndLinking contains the format of the log parameter.
	FormatAndLinking uint8
	// Data contains the payload of the log parameter.
	Data []byte
}

// LogSenseParameters returns the parameters of a log page. The returned map
// contains one entry per parameter ID in the result. The order of parameters
// of the same ID is kept.
func (d *Device) LogSenseParameters(r LogSenseRequest) (map[uint16][]LogParameter, error) {
	raw, err := d.LogSenseRaw(r)
	if err != nil {
		return nil, err
	}
	res := make(map[uint16][]LogParameter)
	for {
		if len(raw) == 0 {
			break
		}
		if len(raw) < 4 {
			return nil, errors.New("not enough data left to read full parameter metadata")
		}
		var param LogParameter
		parameterCode := binary.BigEndian.Uint16(raw[0:2])
		param.DisableUpdate = raw[2]&(1<<7) != 0
		param.TargetSaveDisable = raw[2]&(1<<5) != 0
		param.FormatAndLinking = raw[2] & 0b11
		if int(raw[3]) > len(raw)-4 {
			fmt.Println(raw[3], len(raw))
			return nil, errors.New("unable to read parameter, not enough data for indicated length")
		}
		param.Data = raw[4 : int(raw[3])+4]
		raw = raw[int(raw[3])+4:]
		res[parameterCode] = append(res[parameterCode], param)
	}
	return res, nil
}
