/** @defgroup LittleFootFunctions LittleFoot Functions
    Functions available in the LittleFoot language
    @{
*/

/** Reads and returns the value of a single byte from the heap.

    @param byteIndex    the index (in bytes) of the byte to read
    @returns            the value of the byte
*/
int getHeapByte (int byteIndex);

/** Reads 4 bytes from the heap and returns the value as an integer.

    @param byteIndex    the index (in bytes) of the start of the 4 bytes to read
    @returns            the value of the 4 bytes as an integer
*/
int getHeapInt (int byteIndex);

/** Reads a sequence of bits from the heap and returns the value as an integer.

    @param startBitIndex    the index (in bits) of the start of the sequence of bits to read
    @param numBits          how many bits to read
    @returns                the value of the sequence of bits as an integer
*/
int getHeapBits (int startBitIndex, int numBits);

/** Writes a single byte to the heap.

    @param byteIndex    the index (in bytes) of the byte to set
    @param newValue     the new value to set this byte to
*/
void setHeapByte (int byteIndex, int newValue);

/** Writes 4 bytes to the heap.

    @param byteIndex    the index (in bytes) of the start of the 4 bytes to set
    @param newValue     the new value to set the 4 bytes to
*/
void setHeapInt (int byteIndex, int newValue);

/** Returns the smaller of two integer values.

    @param a The first parameter
    @param b The second parameter
    @retval The minimum of a and b
*/
int min (int a, int b);

/** Returns the smaller of two floating point values.

    @param a The first parameter
    @param b The second parameter
    @retval The minimum of a and b
*/
float min (float a, float b);

/** Returns the larger of two integer values.

    @param a The first parameter
    @param b The second parameter
    @retval The maximum of a and b
*/
int max (int a, int b);

/** Returns the larger of two floating point values.

    @param a The first parameter
    @param b The second parameter
    @retval The maximum of a and b
*/
float max (float a, float b);

/** Constrains an integer value to keep it within a given range.

    @param lowerLimit          the minimum value to return
    @param upperLimit          the maximum value to return
    @param valueToConstrain    the value to try to return
    @returns                   the closest value to valueToConstrain which lies between lowerLimit
                               and upperLimit (inclusive)
*/
int clamp (int lowerLimit, int upperLimit, int valueToConstrain);

/** Constrains a floating point value to keep it within a given range.

    @param lowerLimit          the minimum value to return
    @param upperLimit          the maximum value to return
    @param valueToConstrain    the value to try to return
    @returns                   the closest value to valueToConstrain which lies between lowerLimit
                               and upperLimit (inclusive)
*/
float clamp (float lowerLimit, float upperLimit, float valueToConstrain);

/** Returns the absolute value of an integer value.

    @param arg The argument to compute the absolute value of
    @retval either -arg if arg is negative or arg if arg is positive
*/
int abs (int arg);

/** Returns the absolute value of a floating point value.

    @param arg The argument to compute the absolute value of
    @retval either -arg if arg is negative or arg if arg is positive
*/
float abs (float arg);

/** Remaps a value from a source range to a target range.

    @param value        the value within the source range to map
    @param sourceMin    the minimum value of the source range
    @param sourceMax    the maximum value of the source range
    @param destMin      the minimum value of the destination range
    @param destMax      the maximum value of the destination range
    @returns            the original value mapped to the destination range
*/
float map (float value, float sourceMin, float sourceMax, float destMin, float destMax);

/** Remaps a value from a source range to the range 0 - 1.0.

    @param value        the value within the source range to map
    @param sourceMin    the minimum value of the source range
    @param sourceMax    the maximum value of the source range
    @returns            the original value mapped to the range 0 - 1.0
*/
float map (float value, float sourceMin, float sourceMax);

/** Performs a modulo operation (can cope with the dividend being negative).
    The divisor must be greater than zero.

    @returns    the result of the modulo operation
*/
int mod (int dividend, int divisor);

/** Returns a random floating-point number.

    @returns    a random value in the range 0 (inclusive) to 1.0 (exclusive)
*/
float getRandomFloat();

/** Returns a random integer, limited to a given range.

    @returns    a random integer between 0 (inclusive) and maxValue (exclusive).
*/
int getRandomInt (int maxValue);

/** Returns the number of milliseconds since a fixed event (usually system startup).

    @returns     a monotonically increasing value which is unaffected by changes to the
                 system clock. It should be accurate to within a few millisecseconds.
*/
int getMillisecondCounter();

/** Returns the length of time spent in the current function call in milliseconds.

    @returns     the length of time spent in the current function call in milliseconds.
*/
int getTimeInCurrentFunctionCall();

/** Logs an integer value to the console.

    @param data The 32 bit signed integer to log to the topology as an integer
*/
void log (int data);

/** Logs a hexadecimal value to the console.

    @param data The 32 bit signed integer to log to the topology as a hexidecimal int
*/
void logHex (int data);

/** Sends a 1-byte short midi message. */
void sendMIDI (int byte0);

/** Sends a 2-byte short midi message. */
void sendMIDI (int byte0, int byte1);

/** Sends a 3-byte short midi message. */
void sendMIDI  (int byte0, int byte1, int byte2);

/** Sends a key-down message.

    @param channel       the midi channel, in the range 0 to 15
    @param noteNumber    the key number, in the range 0 to 127
    @param velocity      the velocity, in the range 0 to 127
*/
void sendNoteOn (int channel, int noteNumber, int velocity);

/** Sends a key-up message.

    @param channel       the midi channel, in the range 0 to 15
    @param noteNumber    the key number, in the range 0 to 127
    @param velocity      the velocity, in the range 0 to 127
*/
void sendNoteOff (int channel, int noteNumber, int velocity);

/** Sends an aftertouch message.

    @param channel       the midi channel, in the range 0 to 15
    @param noteNumber    the key number, in the range 0 to 127
    @param level         the amount of aftertouch, in the range 0 to 127
*/
void sendAftertouch (int channel, int noteNumber, int level);

/** Sends a controller message.

    @param channel       the midi channel, in the range 0 to 15
    @param controller    the type of controller
    @param value         the controller value
*/
void sendCC (int channel, int controller, int value);

/** Sends a pitch bend message.

    @param channel     the midi channel, in the range 0 to 15
    @param position    the wheel position, in the range 0 to 16383
*/
void sendPitchBend (int channel, int position);

/** Sends a channel-pressure change event.

    @param channel     the midi channel, in the range 0 to 15
    @param pressure    the pressure, in the range 0 to 127
*/
void sendChannelPressure (int channel, int pressure);

/** Sets the MIDI channel range.

    @param useMPE         whether to use MPE mode
    @param lowChannel     the lowest MIDI channel
    @param highChannel    the highest MIDI channel
*/
void setChannelRange (bool useMPE, int lowChannel, int highChannel);

/** Assigns a MIDI channel to a note number.

    @param noteNumber    the note number to assign the channel to
    @returns             the MIDI channel that has been assigned
*/
int assignChannel (int noteNumber);

/** Deassigns a channel from a note number.

    @param noteNumber    the note number to deassign
    @param channel       the MIDI channel
*/
void deassignChannel (int noteNumber, int channel);

/** Returns the channel that is being used for control messages.

    @returns the channel that is being used for control messages. (If MPE is enabled then this will be the first channel.)
*/
int getControlChannel();

/** Sets whether duplicate notes should be filtered out when MPE is enabled. */
void useMPEDuplicateFilter (bool active);

/** Use this method to draw the display.
    The block will call this approximately 25 times per second.
*/
void repaint();

/** Called when a button is pushed.

    @param index    the index of the button that was pushed
*/
void handleButtonDown (int index);

/** Called when a button is released.

    @param index    the index of the button that was released
*/
void handleButtonUp (int index);

/** Call this when a control block button is pressed to trigger the buttons default behaviour.

    @param buttonIndex    the index of the button

    @note Requires >= 0.2.5 firmware
    @note Only valid with a control block

    @see initControl onControlRelease
*/
void onControlPress (int buttonIndex);

/** Call this when a control block button is released to trigger the buttons default behaviour.

    @param buttonIndex    the index of the button

    @note Requires >= 0.2.5 firmware
    @note Only valid with a control block

    @see initControl onControlPress
*/
void onControlRelease (int buttonIndex);

/** Called when a touch event starts.

    Block units follow the number of DNA connectors on the side of the device.
    For instance, a Lightpad Block is 2x2 and a Control Block is 2x1.

    @param index    the touch index, which will stay constant for each finger as it is tracked
    @param x        the X position of this touch on the device, in block units starting from 0 (left)
    @param y        the Y position of this touch on the device, in block units starting from 0 (top)
    @param z        the current pressure of this touch, in the range 0.0 (no pressure) to 1.0 (very hard)
    @param vz       the rate at which pressure is currently changing, measured in units/second
*/
void touchStart (int index, float x, float y, float z, float vz);

/** Called when a touch event moves.

    Block units follow the number of DNA connectors on the side of the device.
    For instance, a Lightpad Block is 2x2 and a Control Block is 2x1.

    @param index    the touch index, which will stay constant for each finger as it is tracked
    @param x        the X position of this touch on the device, in block units starting from 0 (left)
    @param y        the Y position of this touch on the device, in block units starting from 0 (top)
    @param z        the current pressure of this touch, in the range 0.0 (no pressure) to 1.0 (very hard)
    @param vz       the rate at which pressure is currently changing, measured in units/second
*/
void touchMove (int index, float x, float y, float z, float vz);

/** Called when a touch event ends.

    Block units follow the number of DNA connectors on the side of the device.
    For instance, a Lightpad Block is 2x2 and a Control Block is 2x1.

    @param index    the touch index, which will stay constant for each finger as it is tracked
    @param x        the X position of this touch on the device, in block units starting from 0 (left)
    @param y        the Y position of this touch on the device, in block units starting from 0 (top)
    @param z        the current pressure of this touch, in the range 0.0 (no pressure) to 1.0 (very hard)
    @param vz       the rate at which pressure is currently changing, measured in units/second
*/
void touchEnd (int index, float x, float y, float z, float vz);

/** Called when a program is loaded onto the block and is about to start. Do any setup here. */
void initialise();

/** Called when a block receives a MIDI message. */
void handleMIDI (int byte0, int byte1, int byte2);

/** Called when a block receives a message.

    @see sendMessageToBlock
*/
void handleMessage (int param1, int param2, int param3);

/** Combines a set of 8-bit ARGB values into a 32-bit colour and returns the result.

    @return a 32-bit colour
    @param alpha The alpha in range 0 - 255 inclusive
    @param red The red in range 0 - 255 inclusive
    @param green The green in range 0 - 255 inclusive
    @param blue The blue in range 0 - 255 inclusive
*/
int makeARGB (int alpha, int red, int green, int blue);

/** Blends the overlaid ARGB colour onto the base one and returns the new colour.

    @param baseColour the colour to blend on to
    @param overlaidColour The colour to blend in to the baseColour
    @returns The blended colour
*/
int blendARGB (int baseColour, int overlaidColour);

/** Displays an animation indicating the current battery level of this block.
    A control block will light up its top LEDs indicating battery level and a lightpad
    block will draw the battery level on the display.

    @note Requires >= 0.2.5 firmware
*/
void displayBatteryLevel();

/** Clears the display and sets all the LEDs to black. */
void clearDisplay();

/** Clears the display and sets all the LEDs to a specified colour.

    @param rgb    the colour to use (0xff...)
*/
void clearDisplay (int rgb);

/** Sets a pixel to a specified colour with full alpha.

    @param rgb    the colour to use (0xff...)
    @param x      the x coordinate of the pixel to fill
    @param y      the y coordinate of the pixel to fill
*/
void fillPixel (int rgb, int x, int y);

/** Blends the current pixel colour with a specified colour.

    @param argb    the colour to use
    @param x       the x coordinate of the pixel to blend
    @param y       the y coordinate of the pixel to blend
*/
void blendPixel (int argb, int x, int y);

/** Fills a rectangle on the display with a specified colour.

    @param rgb       the colour to use (0xff...)
    @param x         the x coordinate of the rectangle to draw
    @param y         the y coordinate of the rectangle to draw
    @param width     the width of the rectangle to draw
    @param height    the height of the rectangle to draw
*/
void fillRect (int rgb, int x, int y, int width, int height);

/** Blends a rectangle on the display with a specified colour.

    @param argb      the colour to use
    @param x         the x coordinate of the rectangle to blend
    @param y         the y coordinate of the rectangle to blend
    @param width     the width of the rectangle to blend
    @param height    the height of the rectangle to blend
*/
void blendRect (int argb, int x, int y, int width, int height);

/** Fills a rectangle on the display with four corner colours blended together.

    @param colourNW    the colour to use in the north west corner of the rectangle
    @param colourNE    the colour to use in the north east corner of the rectangle
    @param colourSE    the colour to use in the south east corner of the rectangle
    @param colourSW    the colour to use in the south west corner of the rectangle
    @param x           the x coordinate of the rectangle
    @param y           the y coordinate of the rectangle
    @param width       the width of the rectangle
    @param height      the height of the rectangle
*/
void blendGradientRect (int colourNW, int colourNE, int colourSE, int colourSW, int x, int y, int width, int height);

/** Blends a circle on the display with a specified colour.

    @param argb       the colour to use
    @param xCentre    the x position of the circle's centre in block units
    @param yCentre    the y position of the circle's centre in block units
    @param radius     the radius of the circle in block units
    @param fill       if true then the circle will be filled, if false the circle will be an outline

    @note Requires >= 0.2.5 firmware
*/
void blendCircle (int argb, float xCentre, float yCentre, float radius, bool fill);

/** Draws a number on the display.

    @param value     the number to draw between 0 and 99
    @param colour    the colour to use
    @param x         the x coordinate to use
    @param y         the y coordinate to use
*/
void drawNumber (int value, int colour, int x, int y);

/** Returns the current firmware version of this block.

    @returns The firmware version of the form 0xMJMIRV (where MJ = Major, MI = Minor, RV = Revision)

    @note Requires >= 0.2.5 firmware
*/
int getFirmwareVersion();

/** Returns the battery level of this block, between 0 and 1.0.

    @returns the battery level of this block, between 0 and 1.0.

    @note Requires >= 0.2.5 firmware
*/
float getBatteryLevel();

/** Returns true if this block's battery is charging.

    @returns true if this block's battery is charging

    @note Requires >= 0.2.5 firmware
*/
bool isBatteryCharging();

/** Sets whether status overlays should be displayed on this block.

    @note Requires >= 0.2.5 firmware
*/
void setStatusOverlayActive (bool active);

/** Sets whether power saving mode should be enabled on this block.

    @note Requires >= 0.2.5 firmware
*/
void setPowerSavingEnabled (bool enabled);

/** Returns the type of the block with a given ID.

    @returns    an enum indicating the type of block @see Block::Type

    @note Requires >= 0.2.5 firmware
*/
int getBlockTypeForID (int blockID);

/** Sends a message to the block with the specified ID.
    This will be processed in the handleMessage() callback.

    @param blockID    the ID of the block to send this message to
    @param param1     the first chunk of data to send
    @param param2     the second chunk of data to send
    @param param3     the third chunk of data to send
*/
void sendMessageToBlock (int blockID, int param1, int param2, int param3);

/** Sends a message to the host. To receive this the host will need to implement
    the Block::ProgramEventListener::handleProgramEvent() method.

    @param param1    the first chunk of data to send
    @param param2    the second chunk of data to send
    @param param3    the third chunk of data to send
*/
void sendMessageToHost (int param1, int param2, int param3);

/** Draws a pressure point with a specified colour and pressure.

    @param argb      the colour to use
    @param touchX    the x position of the touch in block units
    @param touchY    the y position of the touch in block units
    @param touchZ    the pressure value of the touch
*/
void addPressurePoint (int argb, float touchX, float touchY, float touchZ);

/** Draws the pressure map on the display. */
void drawPressureMap();

/** Fades the pressure map on the display. */
void fadePressureMap();

/** Links a another block to this control block.

    @param blockID    the ID of the block to link

    @note Requires >= 0.2.5 firmware
    @note Only valid with a control block
*/
void linkBlockIDtoController (int blockID);

/** Repaints the control block display.

    @note Requires >= 0.2.5 firmware
    @note Only valid with a control block
*/
void repaintControl();

/** Initialises one of the control block buttons.

    @param buttonIndex       the index of the button to initialise
    @param modeToUse         the mode to use for this button @see ControlMode
    @param outputType        the control type to use @see ControlType
    @param val               the current value to set this button to
    @param min               the minimum value for this button
    @param max               the maximum value for this button
    @param index             the item index
    @param onColourToUse     the colour to use when this button is on
    @param offColourToUse    the colour to use when this button is off

    @note Requires >= 0.2.5 firmware
    @note Only valid with a control block
*/
void initControl (int buttonIndex, int modeToUse, int outputType, int val, int min, int max,
                  int index,  int onColourToUse, int offColourToUse);

/** Control type for use with initControl

    @see initControl
*/
enum ControlType
{
    internalConfig = 0,
    midiCC,
    sysex
};

/** Control mode for use with initControl

    @see initControl
*/
enum ControlMode
{
    toggle = 0,
    togglePulse,
    gate,
    trigger,
    cycle,
    incDec,
    triState
};

/** Forces a touch event to be handled as seaboard playing.

    @param touchIndex    the index of the touch event

    @note Requires >= 0.2.5 firmware
    @note Only valid on a Seaboard
*/
void handleTouchAsSeaboard (int touchIndex);

/** Returns the number of blocks in the current topology.

    @note Requires >= 0.2.5 firmware
*/
int getNumBlocksInTopology();

/** Returns the ID of a block at a given index in the topology.

    @param index The index of the block to find in the topology
    @returns int The id of the block

    @note Requires >= 0.2.5 firmware
*/
int getBlockIDForIndex (int index);

/** Returns true if this block is directly connected to the host,
    as opposed to only being connected to a different block via a connection port.

    @note Requires >= 0.2.5 firmware
*/
bool isMasterBlock();

/** Returns true if this block is connected to the host computer, this can be
    directly or through connections to other blocks.

    @note Requires >= 0.2.5 firmware
*/
bool isConnectedToHost();

/** Returns the ID of a block connected to a specified port on this block.

    @note Requires >= 0.2.5 firmware
*/
int getBlockIDOnPort (int port);

/** Returns the port number that is connected to the master block. Returns 0xFF if there is
    no port connected to master.

    @returns the port number that is connected to the master block. Returns 0xFF if there is
             no port connected to master.

    @note Requires >= 0.2.5 firmware
*/
int getPortToMaster();

/** Returns the horizontal distance between this block and the master block in block units.

    @note Requires >= 0.2.5 firmware
*/
int getHorizontalDistFromMaster();

/** Returns the vertical distance between this block and the master block in block units.

    @note Requires >= 0.2.5 firmware
*/
int getVerticalDistFromMaster();

/** Returns the angle of this block relative to the master block in degrees.

    @note Requires >= 0.2.5 firmware
*/
int getAngleFromMaster();

/** Sets whether this block should auto-rotate when its angle relative to the master block changes.

    @note Requires >= 0.2.5 firmware
*/
void setAutoRotate (bool enabled);

/** Returns the index of this block in the current cluster.

    @note Requires >= 0.2.5 firmware
*/
int getClusterIndex();

/** Returns how many blocks wide the current cluster is.

    @returns the width of the cluster (note that a single block will return 1 here)

    @note Requires >= 0.2.5 firmware
*/
int getClusterWidth();

/** Returns how many blocks high the current cluster is.

    @returns the height of the cluster (note that a single block will return 1 here)

    @note Requires >= 0.2.5 firmware
*/
int getClusterHeight();

/** Returns the x index of this block in the current cluster.

    @returns int The cluster x position. (0, 0) is considered to be the top left block

    @note Requires >= 0.2.5 firmware
*/
int getClusterXpos();

/** Returns the y index of this block in the current cluster.

    @returns int The cluster x position. (0, 0) is considered to be the top left block

    @note Requires >= 0.2.5 firmware
*/
int getClusterYpos();

/** Returns the number of blocks in the current cluster.

    @returns the number of blocks in the current cluster.

    @note Requires >= 0.2.5 firmware
*/
int getNumBlocksInCurrentCluster();

/** Returns the block ID for a block in the current cluster.

    @param index    the cluster index of the block to get the ID of

    @note Requires >= 0.2.5 firmware
*/
int getBlockIdForBlockInCluster (int index);

/** Returns true if the master block is in the current cluster.

    @note Requires >= 0.2.5 firmware
*/
bool isMasterInCurrentCluster();

/** Returns current value of one of the local config items.

    @param item    the config item to get (see ConfigItemId enum in juce_BlocksProtocolDefinitions.h)

    @note Requires >= 0.2.5 firmware
*/
int getLocalConfig (int item);

/** Sets the current value of one of the local config items.

    @param item     the config item to set the value of (see ConfigItemId enum in juce_BlocksProtocolDefinitions.h)
    @param value    the value to set the config to

    @note Requires >= 0.2.5 firmware
*/
void setLocalConfig (int item, int value);

/** Sets the local config of a block to the config item of a remote block.

    @param longAddress    the address of the remote block
    @param item           the config item (see ConfigItemId enum in juce_BlocksProtocolDefinitions.h)

    @note Requires >= 0.2.5 firmware
*/
void requestRemoteConfig (int longAddress, int item);

/** Sets the config of a remote block.

    @param longAddress    the address of the remote block
    @param item           the config item (see ConfigItemId enum in juce_BlocksProtocolDefinitions.h)
    @param value          the value to set the config to

    @note Requires >= 0.2.5 firmware
*/
void setRemoteConfig (int longAddress, int item, int value);

/** Sets the range of one of the local config items.

    @param item    the config item to set the range of (see ConfigItemId enum in juce_BlocksProtocolDefinitions.h)
    @param min     the minimum value this config item should use
    @param max     the maximum value this config item should use

    @note Requires >= 0.2.5 firmware
*/
void setLocalConfigItemRange (int item, int min, int max);

/** Sets whether a local config item should be active.

    @param item           the config item to set active (see ConfigItemId enum in juce_BlocksProtocolDefinitions.h)
    @param isActive       sets whether the config should be active or not
    @param saveToFlash    if true then this config item will be saved to the flash memory of the block

    @note Requires >= 0.2.5 firmware
*/
void setLocalConfigActiveState (int item, bool isActive, bool saveToFlash);

/** @} */
