package devicetree

import (
	"bytes"
	"errors"
	"fmt"

	"github.com/blacktop/ipsw/internal/utils"
	"github.com/blacktop/ipsw/pkg/img3"
	"github.com/blacktop/ipsw/pkg/img4"
)

var ErrEncryptedDeviceTree = errors.New("encrypted device tree")

// ParseImg3Data parses a img3 data containing a DeviceTree
func ParseImg3Data(data []byte) (*DeviceTree, error) {
	// First try to extract data (handles both encrypted detection and data extraction)
	extractedData, err := img3.ExtractData(data)
	if err != nil {
		// Check if this might be an encrypted IMG3 by parsing and looking for KBAG tags
		i, parseErr := img3.ParseImg3(data)
		if parseErr == nil {
			for _, tag := range i.Tags {
				magic := string(utils.ReverseBytes(tag.Magic[:]))
				if magic == "KBAG" {
					return nil, ErrEncryptedDeviceTree
				}
			}
		}
		return nil, fmt.Errorf("failed to extract IMG3 data: %v", err)
	}

	dr := bytes.NewReader(extractedData)

	dtree, err := parseDeviceTree(dr)
	if err != nil {
		return nil, fmt.Errorf("failed to parse IMG3 device tree data: %v", err)
	}

	return dtree, nil
}

// ParseImg4Data parses a img4 data containing a DeviceTree
func ParseImg4Data(data []byte) (*DeviceTree, error) {

	// NOTE: openssl asn1parse -i -inform DER -in DEVICETREE.im4p
	im4p, err := img4.ParsePayload(data)
	if err != nil {
		return nil, fmt.Errorf("failed to parse Img4 payload: %v", err)
	}

	// Check if the payload is encrypted before attempting to parse
	if im4p.Encrypted {
		return nil, ErrEncryptedDeviceTree
	}

	data, err = im4p.GetData()
	if err != nil {
		return nil, fmt.Errorf("failed to get Img4 data: %v", err)
	}

	dtree, err := parseDeviceTree(bytes.NewReader(data))
	if err != nil {
		return nil, fmt.Errorf("failed to parse Img4 device tree data: %v", err)
	}

	return dtree, nil
}
