//
//  CanonPTPCommandsTests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

/// Canon PTP 命令与事件解析测试。
final class CanonPTPCommandsTests: XCTestCase {
    /// 测试 SetRemoteMode 命令包 opcode。
    func testBuildSetRemoteModeCommand() {
        let data = PTPHelper.buildCommand(
            code: CanonPTPCommand.eosSetRemoteMode,
            transactionID: 1,
            parameters: [1]
        )

        XCTAssertEqual(data.count, 16)
        XCTAssertEqual(data[6], 0x14)
        XCTAssertEqual(data[7], 0x91)
    }

    /// 测试 ObjectAddedEx (0xC181) 事件解析。
    func testParseObjectAddedExEvent() {
        var blob = Data()
        let recordSize: UInt32 = 8 + 40
        blob.append(contentsOf: withUnsafeBytes(of: recordSize.littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: CanonPTPCommand.eosObjectAddedEx.littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0x1234).littleEndian) { Data($0) }) // handle
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0x00010001).littleEndian) { Data($0) }) // storage
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0x3801).littleEndian) { Data($0) }) // ofc
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) }) // flags
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) }) // parent
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) }) // reserved
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(1024).littleEndian) { Data($0) }) // size
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) }) // reserved
        let filename = "IMG_0001.JPG"
        blob.append(filename.data(using: .ascii)!)
        blob.append(0)

        let events = CanonEosEventParser.parse(blob)
        XCTAssertEqual(events.count, 1)
        guard case .objectAdded(let added) = events[0] else {
            return XCTFail("expected objectAdded")
        }
        XCTAssertEqual(added.objectHandle, 0x1234)
        XCTAssertEqual(added.filename, "IMG_0001.JPG")
        XCTAssertEqual(added.size, 1024)
    }

    /// 测试 ObjectAddedEx2 (0xC1A7) 大文件 size 解析。
    func testParseObjectAddedEx2Event() {
        var blob = Data()
        let recordSize: UInt32 = 8 + 48
        blob.append(contentsOf: withUnsafeBytes(of: recordSize.littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: CanonPTPCommand.eosObjectAddedEx2.littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0x5678).littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0x00010001).littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0x3801).littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(512).littleEndian) { Data($0) }) // sizeLow
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(1).littleEndian) { Data($0) }) // sizeHigh
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) })
        blob.append(contentsOf: withUnsafeBytes(of: UInt32(0).littleEndian) { Data($0) })
        blob.append("LARGE.JPG".data(using: .ascii)!)
        blob.append(0)

        let events = CanonEosEventParser.parse(blob)
        XCTAssertEqual(events.count, 1)
        guard case .objectAdded(let added) = events[0] else {
            return XCTFail("expected objectAdded")
        }
        XCTAssertEqual(added.objectHandle, 0x5678)
        XCTAssertEqual(added.size, 512 | (1 << 32))
    }

    /// 测试支持的文件名扩展名过滤。
    func testSupportedFilenameExtensions() {
        XCTAssertTrue(CanonPTPHelper.isSupportedFilename("photo.JPG"))
        XCTAssertTrue(CanonPTPHelper.isSupportedFilename("photo.cr2"))
        XCTAssertFalse(CanonPTPHelper.isSupportedFilename("photo.tif"))
    }
}
