// This file was autogenerated by the `uniffi-bindgen-gecko-js` crate.
// Trust me, you don't want to mess with it!

import {
  ArrayBufferDataStream,
  FfiConverter,
  FfiConverterArrayBuffer,
  FfiConverterInt8,
  FfiConverterUInt8,
  FfiConverterInt16,
  FfiConverterUInt16,
  FfiConverterInt32,
  FfiConverterUInt32,
  FfiConverterInt64,
  FfiConverterUInt64,
  FfiConverterFloat32,
  FfiConverterFloat64,
  FfiConverterBoolean,
  FfiConverterBytes,
  FfiConverterString,
  UniFFICallbackHandler,
  UniFFICallbackMethodHandler,
  UniFFIError,
  UniFFIInternalError,
  UniFFITypeError,
  constructUniffiObject,
  handleRustResult,
  uniffiObjectPtr,
} from "moz-src:///toolkit/components/uniffi-js/js/UniFFI.sys.mjs";

// Objects intended to be used in the unit tests
export var UnitTestObjs = {
    uniffiObjectPtr,
};
/**
 * registerEventSink
 * @param {EventSinkSpecification} targets
 * @param {EventSink} sink
 * @returns {EventSinkId}
 */
export function registerEventSink(
    targets, 
    sink) {
   
FfiConverterTypeEventSinkSpecification.checkType(targets);
FfiConverterTypeEventSink.checkType(sink);
const result = UniFFIScaffolding.callSync(
    224, // uniffi_tracing_support_fn_func_register_event_sink
    FfiConverterTypeEventSinkSpecification.lower(targets),
    FfiConverterTypeEventSink.lower(sink),
)
return handleRustResult(
    result,
    FfiConverterTypeEventSinkId.lift.bind(FfiConverterTypeEventSinkId),
    null,
)
}

/**
 * unregisterEventSink
 * @param {EventSinkId} id
 */
export function unregisterEventSink(
    id) {
   
FfiConverterTypeEventSinkId.checkType(id);
const result = UniFFIScaffolding.callSync(
    225, // uniffi_tracing_support_fn_func_unregister_event_sink
    FfiConverterTypeEventSinkId.lower(id),
)
return handleRustResult(
    result,
    (result) => undefined,
    null,
)
}





/**
 * TracingLevel
 */
export const TracingLevel = Object.freeze({
    /**
     * ERROR
     */
    ERROR: 0,
    /**
     * WARN
     */
    WARN: 1,
    /**
     * INFO
     */
    INFO: 2,
    /**
     * DEBUG
     */
    DEBUG: 3,
    /**
     * TRACE
     */
    TRACE: 4,
});

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeTracingLevel extends FfiConverterArrayBuffer {
    static #validValues = Object.values(TracingLevel)

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return TracingLevel.ERROR
            case 2:
                return TracingLevel.WARN
            case 3:
                return TracingLevel.INFO
            case 4:
                return TracingLevel.DEBUG
            case 5:
                return TracingLevel.TRACE
            default:
                throw new UniFFITypeError("Unknown TracingLevel variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value === TracingLevel.ERROR) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === TracingLevel.WARN) {
            dataStream.writeInt32(2);
            return;
        }
        if (value === TracingLevel.INFO) {
            dataStream.writeInt32(3);
            return;
        }
        if (value === TracingLevel.DEBUG) {
            dataStream.writeInt32(4);
            return;
        }
        if (value === TracingLevel.TRACE) {
            dataStream.writeInt32(5);
            return;
        }
        throw new UniFFITypeError("Unknown TracingLevel variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      // Check that the value is a valid enum variant
      if (!this.#validValues.includes(value)) {
          throw new UniFFITypeError(`${value} is not a valid value for TracingLevel`);
      }
    }
}
/**
 * EventTarget
 */
export class EventTarget {
    constructor(
        {
            target, 
            level
        } = {
            target: undefined, 
            level: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(target)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("target");
            }
            throw e;
        }
        try {
            FfiConverterTypeTracingLevel.checkType(level)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("level");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.target = target;
        /**
         * @type {TracingLevel[keyof TracingLevel]}
         */
        this.level = level;
    }

    equals(other) {
        return (
            this.target == other.target
            && this.level == other.level
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeEventTarget extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new EventTarget({
            target: FfiConverterString.read(dataStream),
            level: FfiConverterTypeTracingLevel.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.target);
        FfiConverterTypeTracingLevel.write(dataStream, value.level);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.target);
        totalSize += FfiConverterTypeTracingLevel.computeSize(value.level);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof EventTarget)) {
            throw new UniFFITypeError(`Expected 'EventTarget', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.target);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".target");
            }
            throw e;
        }
        try {
            FfiConverterTypeTracingLevel.checkType(value.level);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".level");
            }
            throw e;
        }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeEventTarget extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeEventTarget.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterTypeEventTarget.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterTypeEventTarget.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeEventTarget.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeTracingLevel extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeTracingLevel.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeTracingLevel.read(dataStream)
            default:
                throw new UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterTypeTracingLevel.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeTracingLevel.computeSize(value)
    }
}
/**
 * Describes which events to an EventSink
 */
export class EventSinkSpecification {
    constructor(
        {
            targets= [], 
            minLevel= null
        } = {
            targets: undefined, 
            minLevel: undefined
        }
    ) {
        try {
            FfiConverterSequenceTypeEventTarget.checkType(targets)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("targets");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeTracingLevel.checkType(minLevel)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("minLevel");
            }
            throw e;
        }
        /**
         * @type {Array.<EventTarget>}
         */
        this.targets = targets;
        /**
         * @type {?TracingLevel[keyof TracingLevel]}
         */
        this.minLevel = minLevel;
    }

    equals(other) {
        return (
            this.targets == other.targets
            && this.minLevel == other.minLevel
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeEventSinkSpecification extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new EventSinkSpecification({
            targets: FfiConverterSequenceTypeEventTarget.read(dataStream),
            minLevel: FfiConverterOptionalTypeTracingLevel.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterSequenceTypeEventTarget.write(dataStream, value.targets);
        FfiConverterOptionalTypeTracingLevel.write(dataStream, value.minLevel);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterSequenceTypeEventTarget.computeSize(value.targets);
        totalSize += FfiConverterOptionalTypeTracingLevel.computeSize(value.minLevel);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof EventSinkSpecification)) {
            throw new UniFFITypeError(`Expected 'EventSinkSpecification', found '${typeof value}'`);
        }
        try {
            FfiConverterSequenceTypeEventTarget.checkType(value.targets);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".targets");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeTracingLevel.checkType(value.minLevel);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".minLevel");
            }
            throw e;
        }
    }
}
export class FfiConverterTypeTracingJsonValue extends FfiConverter {
    static lift(value) {
        return FfiConverterString.lift(value);
    }

    static lower(value) {
        return FfiConverterString.lower(value);
    }

    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value);
    }

    static read(dataStream) {
        const builtinVal = FfiConverterString.read(dataStream);
        return builtinVal;
    }

    static computeSize(value) {
        return FfiConverterString.computeSize(value);
    }

    static checkType(value) {
        if (value === null || value === undefined) {
            throw new TypeError("value is null or undefined");
        }
    }
}
/**
 * TracingEvent
 */
export class TracingEvent {
    constructor(
        {
            level, 
            target, 
            name, 
            message, 
            fields
        } = {
            level: undefined, 
            target: undefined, 
            name: undefined, 
            message: undefined, 
            fields: undefined
        }
    ) {
        try {
            FfiConverterTypeTracingLevel.checkType(level)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("level");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(target)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("target");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(name)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("name");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(message)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("message");
            }
            throw e;
        }
        try {
            FfiConverterTypeTracingJsonValue.checkType(fields)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("fields");
            }
            throw e;
        }
        /**
         * @type {TracingLevel[keyof TracingLevel]}
         */
        this.level = level;
        /**
         * @type {string}
         */
        this.target = target;
        /**
         * @type {string}
         */
        this.name = name;
        /**
         * @type {string}
         */
        this.message = message;
        /**
         * @type {TracingJsonValue}
         */
        this.fields = fields;
    }

    equals(other) {
        return (
            this.level == other.level
            && this.target == other.target
            && this.name == other.name
            && this.message == other.message
            && this.fields == other.fields
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeTracingEvent extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new TracingEvent({
            level: FfiConverterTypeTracingLevel.read(dataStream),
            target: FfiConverterString.read(dataStream),
            name: FfiConverterString.read(dataStream),
            message: FfiConverterString.read(dataStream),
            fields: FfiConverterTypeTracingJsonValue.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterTypeTracingLevel.write(dataStream, value.level);
        FfiConverterString.write(dataStream, value.target);
        FfiConverterString.write(dataStream, value.name);
        FfiConverterString.write(dataStream, value.message);
        FfiConverterTypeTracingJsonValue.write(dataStream, value.fields);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterTypeTracingLevel.computeSize(value.level);
        totalSize += FfiConverterString.computeSize(value.target);
        totalSize += FfiConverterString.computeSize(value.name);
        totalSize += FfiConverterString.computeSize(value.message);
        totalSize += FfiConverterTypeTracingJsonValue.computeSize(value.fields);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof TracingEvent)) {
            throw new UniFFITypeError(`Expected 'TracingEvent', found '${typeof value}'`);
        }
        try {
            FfiConverterTypeTracingLevel.checkType(value.level);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".level");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.target);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".target");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.name);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".name");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.message);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".message");
            }
            throw e;
        }
        try {
            FfiConverterTypeTracingJsonValue.checkType(value.fields);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".fields");
            }
            throw e;
        }
    }
}


export class FfiConverterTypeEventSinkId extends FfiConverter {
    static lift(value) {
        return FfiConverterUInt32.lift(value);
    }

    static lower(value) {
        return FfiConverterUInt32.lower(value);
    }

    static write(dataStream, value) {
        FfiConverterUInt32.write(dataStream, value);
    }

    static read(dataStream) {
        const builtinVal = FfiConverterUInt32.read(dataStream);
        return builtinVal;
    }

    static computeSize(value) {
        return FfiConverterUInt32.computeSize(value);
    }

    static checkType(value) {
        if (value === null || value === undefined) {
            throw new TypeError("value is null or undefined");
        }
    }
}

/**
 * EventSink
 */
export class EventSink {
    /**
     * onEvent
     * @param {TracingEvent} event
     */
    onEvent(
        event) {
      throw Error("onEvent not implemented");
    }

}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeEventSink extends FfiConverter {
    static lower(callbackObj) {
        if (!(callbackObj instanceof EventSink)) {
            throw new UniFFITypeError("expected 'EventSink' subclass");
        }
        return uniffiCallbackHandlerTracingEventSink.storeCallbackObj(callbackObj)
    }

    static lift(handleId) {
        return uniffiCallbackHandlerTracingEventSink.takeCallbackObj(handleId)
    }

    static read(dataStream) {
        return this.lift(dataStream.readInt64())
    }

    static write(dataStream, callbackObj) {
        dataStream.writeInt64(this.lower(callbackObj))
    }

    static computeSize(callbackObj) {
        return 8;
    }
}
const uniffiCallbackHandlerTracingEventSink = new UniFFICallbackHandler(
    "EventSink",
    7,
    [
        new UniFFICallbackMethodHandler(
            "onEvent",
            [
                FfiConverterTypeTracingEvent,
            ],
            (result) => undefined,
            (e) => {
              throw e;
            }
        ),
    ]
);

// Allow the shutdown-related functionality to be tested in the unit tests
UnitTestObjs.uniffiCallbackHandlerTracingEventSink = uniffiCallbackHandlerTracingEventSink;


