/**
 * Copyright (c) 2024 Opal Kelly Incorporated
 *
 * This source code is licensed under the FrontPanel license.
 * See the LICENSE file found in the root directory of this project.
 */

import { ByteCount } from "./CoreDataTypes";

import { WireAddress, WireValue, WireMask } from "./WireEndpoint";
import { TriggerVectorAddress, TriggerVector, TriggerVectorMask } from "./TriggerEndpoint";
import { PipeAddress } from "./Endpoint";
import { RegisterAddress, RegisterValue } from "./Endpoint";

/**
 * Interface that provides the methods that may be used to interact
 * with a FrontPanel device.
 */
interface IFrontPanel {
    /**
     * Gets the value of a WireIn at the specified address.
     * @param address - The address of the WireIn endpoint.
     * @returns {WireValue} - The value of the WireIn.
     */
    getWireInValue(address: WireAddress): WireValue;
    /**
     * Sets the value of the WireIn at the specified address.
     * @param address - The address of the WireIn endpoint.
     * @param value - The value to set.
     * @param mask - The mask to apply to the value.
     */
    setWireInValue(address: WireAddress, value: WireValue, mask: WireMask): void;
    /**
     * Transfers current WireIn values to the FPGA.
     * @returns {Promise<void>} - A promise that resolves when all WireIns have been transfered.
     */
    updateWireIns(): Promise<void>;
    /**
     * Gets the value of the WireOut at the specified address.
     * @param address - The address of the WireOut endpoint.
     * @returns {WireValue} - The value of the WireOut.
     */
    getWireOutValue(address: WireAddress): WireValue;
    /**
     * Retrieves current WireOut values from the FPGA.
     * @returns {Promise<void>} - A promise that resolves when all WireOuts have been updated.
     */
    updateWireOuts(): Promise<void>;
    /**
     * Activates the TriggerIn at the specified address and bit.
     * @param address - The address of the TriggerIn vector endpoint.
     * @param bit - The bit of the TriggerIn vector to activate.
     * @returns {Promise<void>} - A promise that resolves when the TriggerIn has been activated.
     */
    activateTriggerIn(address: TriggerVectorAddress, bit: number): Promise<void>;
    /**
     * Gets the TriggerOut vector at the specified address.
     * @param address - The address of the TriggerOut vector endpoint.
     * @returns {TriggerVector} - The TriggerOut vector.
     */
    getTriggerOutVector(address: TriggerVectorAddress): TriggerVector;
    /**
     * Checks if the TriggerOut at the specified address and mask is active.
     * @param address - The address of the TriggerOut vector endpoint.
     * @param mask - The mask to apply to the TriggerOut vector.
     * @returns {boolean} - True if the TriggerOut is active, otherwise false.
     */
    isTriggered(address: TriggerVectorAddress, mask: TriggerVectorMask): boolean;
    /**
     * Retrieves the current TriggerOut vectors from the FPGA.
     * @returns {Promise<void>} - A promise that resolves when all TriggerOuts have been updated.
     */
    updateTriggerOuts(): Promise<void>;
    /**
     * Writes data to the PipeIn at the specified address.
     * @param address - The address of the PipeIn endpoint.
     * @param length - The length of the data to write in bytes.
     * @param data - The buffer containing the data to write.
     * @returns {Promise<ByteCount>} - A promise that resolves when the data has been written
     * indicating the number of bytes that were successfully written.
     */
    writeToPipeIn(address: PipeAddress, length: ByteCount, data: ArrayBuffer): Promise<ByteCount>;
    /**
     * Writes data to the Block Throttle PipeIn at the specified address.
     * @param address - The address of the PipeIn endpoint.
     * @param blockSize - The size of the blocks to write in bytes.
     * @param length - The length of the data to write in bytes.
     * @param data - The buffer containing the data to write.
     * @returns {Promise<ByteCount>} - A promise that resolves when the data has been written
     * indicating the number of bytes that were successfully written.
     */
    writeToBlockPipeIn(
        address: PipeAddress,
        blockSize: ByteCount,
        length: ByteCount,
        data: ArrayBuffer
    ): Promise<ByteCount>;
    /**
     * Reads data from the PipeOut at the specified address.
     * @param address - The address of the PipeOut endpoint.
     * @param length - The length of the data to read in bytes.
     * @param buffer - The buffer to store the data that is read.
     * @returns {Promise<ByteCount>} - A promise that resolves when the data has been read
     * indicating the number of bytes that were successfully read.
     */
    readFromPipeOut(
        address: PipeAddress,
        length: ByteCount,
        buffer: ArrayBuffer
    ): Promise<ByteCount>;
    /**
     * Reads data from the Block Throttle PipeOut at the specified address.
     * @param address - The address of the PipeOut endpoint.
     * @param blockSize - The size of the blocks to read in bytes.
     * @param length - The length of the data to read in bytes.
     * @param buffer - The buffer to store the data that is read.
     * @returns {Promise<ByteCount>} - A promise that resolves when the data has been read
     * indicating the number of bytes that were successfully read.
     */
    readFromBlockPipeOut(
        address: PipeAddress,
        blockSize: ByteCount,
        length: ByteCount,
        buffer: ArrayBuffer
    ): Promise<ByteCount>;
    /**
     * Reads the value of the Register at the specified address.
     * @param address - The address of the Register.
     * @returns {Promise<RegisterValue>} - A promise that resolves to the value of the Register.
     */
    readRegister(address: RegisterAddress): Promise<RegisterValue>;
    /**
     * Reads the data of the Registers at the specified addresses and stores the data in the
     * corresponding array element.
     * @param registers - The array containing address and data pairs for each register.
     * @returns {Promise<void>} - A promise that resolves when all the registers have
     * been read.
     */
    readRegisters(
        registers: Array<{ address: RegisterAddress; data: RegisterValue }>
    ): Promise<void>;
    /**
     * Writes a value to the Register at the specified address.
     * @param address - The address of the Register.
     * @param value - The value to write.
     * @returns {Promise<void>} - A promise that resolves when the value has been written.
     */
    writeRegister(address: RegisterAddress, value: RegisterValue): Promise<void>;
    /**
     * Writes data to each of the Registers at the specified addresses.
     * @param registers - The array containing address and data pairs for each register.
     * @returns {Promise<void>} - A promise that resolves when the register values have been written.
     */
    writeRegisters(
        registers: Array<{ address: RegisterAddress; data: RegisterValue }>
    ): Promise<void>;
}

export default IFrontPanel;
