/*
  rdm.cpp

  Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
*/

#include "rdm.h"

namespace RDM {

/**
 * @brief ProductCategoryDescription
 * @param PRODUCT_CATEGORY
 * @return
 */
std::string ProductCategoryDescription(const uint16_t PRODUCT_CATEGORY)
{
  switch (PRODUCT_CATEGORY) {
    case PRODUCT_CATEGORY_NOT_DECLARED:
      return std::string("Undeclard");
    /// Fixtures – intended as source of illumination
    case PRODUCT_CATEGORY_FIXTURE:
      return std::string("Fixture");
    case PRODUCT_CATEGORY_FIXTURE_FIXED:
      return std::string("Fixed Fixture");
    case PRODUCT_CATEGORY_FIXTURE_MOVING_YOKE:
      return std::string("Moving Yoke Fixture");
    case PRODUCT_CATEGORY_FIXTURE_MOVING_MIRROR:
      return std::string("Moving Mirror Fixture");
    case PRODUCT_CATEGORY_FIXTURE_OTHER:
      return std::string("Fixture (Other)");
    /// Fixture Accessories – add-ons to fixtures or projectors
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY:
      return std::string("Fixture Accessory");
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_COLOR:
      return std::string("Color Accessory");
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_YOKE:
      return std::string("Yoke Accessory");
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_MIRROR:
      return std::string("Mirror Accessory");
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_EFFECT:
      return std::string("Effect Accessory");
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_BEAM:
      return std::string("Beam Accessory");
    case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_OTHER:
      return std::string("Fixture Accessory (Other)");
    /// Projectors - light source capable of producing realistic images from another media
    case PRODUCT_CATEGORY_PROJECTOR:
      return std::string("Projector");
    case PRODUCT_CATEGORY_PROJECTOR_FIXED:
      return std::string("Fixed Projector");
    case PRODUCT_CATEGORY_PROJECTOR_MOVING_YOKE:
      return std::string("Moving Yoke Projector");
    case PRODUCT_CATEGORY_PROJECTOR_MOVING_MIRROR:
      return std::string("Moving Mirror Projector");
    case PRODUCT_CATEGORY_PROJECTOR_OTHER:
      return std::string("Projector (Other)");
    /// Atmospheric Effect – earth/wind/fire
    case PRODUCT_CATEGORY_ATMOSPHERIC:
      return std::string("Atmospheric");
    case PRODUCT_CATEGORY_ATMOSPHERIC_EFFECT:
      return std::string("Atomospheric Effect");
    case PRODUCT_CATEGORY_ATMOSPHERIC_PYRO:
      return std::string("Pyro");
    case PRODUCT_CATEGORY_ATMOSPHERIC_OTHER:
      return std::string("Atmospheric (other)");
    /// Intensity Control (specifically Dimming equipment)
    case PRODUCT_CATEGORY_DIMMER:
      return std::string("Dimmer");
    case PRODUCT_CATEGORY_DIMMER_AC_INCANDESCENT:
      return std::string("AC Incandescent Dimmer");
    case PRODUCT_CATEGORY_DIMMER_AC_FLUORESCENT:
      return std::string("AC Flourescent Dimmer");
    case PRODUCT_CATEGORY_DIMMER_AC_COLDCATHODE:
      return std::string("AC Cold Cathode Dimmer");
    case PRODUCT_CATEGORY_DIMMER_AC_NONDIM:
      return std::string("AC Non-Dim");
    case PRODUCT_CATEGORY_DIMMER_AC_ELV:
      return std::string("AC Low-Voltage Dimmer");
    case PRODUCT_CATEGORY_DIMMER_AC_OTHER:
      return std::string("AC Dimmer");
    case PRODUCT_CATEGORY_DIMMER_DC_LEVEL:
      return std::string("DC Level Dimmer");
    case PRODUCT_CATEGORY_DIMMER_DC_PWM:
      return std::string("DC PWM Dimmer");
    case PRODUCT_CATEGORY_DIMMER_CS_LED:
      return std::string("LED Dimmer");
    case PRODUCT_CATEGORY_DIMMER_OTHER:
      return std::string("Dimmer (other)");
    /// Power Control (other than Dimming equipment)
    case PRODUCT_CATEGORY_POWER:
      return std::string("Power");
    case PRODUCT_CATEGORY_POWER_CONTROL:
      return std::string("Power Control");
    case PRODUCT_CATEGORY_POWER_SOURCE:
      return std::string("Power Source");
    case PRODUCT_CATEGORY_POWER_OTHER:
      return std::string("Power (other)");
    /// Scenic Drive – including motorized effects unrelated to light source.
    case PRODUCT_CATEGORY_SCENIC:
      return std::string("Scenic");
    case PRODUCT_CATEGORY_SCENIC_DRIVE:
      return std::string("Scenic Drive");
    case PRODUCT_CATEGORY_SCENIC_OTHER:
      return std::string("Scenic (Other)");
    /// DMX Infrastructure, conversion and interfaces
    case PRODUCT_CATEGORY_DATA:
      return std::string("Data");
    case PRODUCT_CATEGORY_DATA_DISTRIBUTION:
      return std::string("Data Distribution");
    case PRODUCT_CATEGORY_DATA_CONVERSION:
      return std::string("Data Converter");
    case PRODUCT_CATEGORY_DATA_OTHER:
      return std::string("Data (Other)");
    /// Audio-Visual Equipment
    case PRODUCT_CATEGORY_AV:
      return std::string("AV");
    case PRODUCT_CATEGORY_AV_AUDIO:
      return std::string("Audio Controller or Device");
    case PRODUCT_CATEGORY_AV_VIDEO:
      return std::string("Video Controller or Display Device");
    case PRODUCT_CATEGORY_AV_OTHER:
      return std::string("AV (Other)");
    /// Parameter Monitoring Equipment
    case PRODUCT_CATEGORY_MONITOR:
      return std::string("Monitor");
    case PRODUCT_CATEGORY_MONITOR_ACLINEPOWER:
      return std::string("AC Line-power Monitor");
    case PRODUCT_CATEGORY_MONITOR_DCPOWER:
      return std::string("DC Power Monitor");
    case PRODUCT_CATEGORY_MONITOR_ENVIRONMENTAL:
      return std::string("Environmental Monitor");
    case PRODUCT_CATEGORY_MONITOR_OTHER:
      return std::string("Monitor (Other)");
    /// Controllers, Backup devices
    case PRODUCT_CATEGORY_CONTROL:
      return std::string("Control");
    case PRODUCT_CATEGORY_CONTROL_CONTROLLER:
      return std::string("Controller");
    case PRODUCT_CATEGORY_CONTROL_BACKUPDEVICE:
      return std::string("Controller-Backup");
    case PRODUCT_CATEGORY_CONTROL_OTHER:
      return std::string("Control (Other)");
    /// Test Equipment
    case PRODUCT_CATEGORY_TEST:
      return std::string("Test");
    case PRODUCT_CATEGORY_TEST_EQUIPMENT:
      return std::string("Test Equipment");
    case PRODUCT_CATEGORY_TEST_EQUIPMENT_OTHER:
      return std::string("Test-Other");
    /// Miscellaneous
    case PRODUCT_CATEGORY_OTHER:
      return std::string("Other");
    default:
      return std::string("Unknown");
    }
}


/**
 * @brief ProductDetailDescription
 * @param PRODUCT_DETAIL
 * @return
 */
std::string ProductDetailDescription(const uint16_t PRODUCT_DETAIL)
{
  switch (PRODUCT_DETAIL) {
    case PRODUCT_DETAIL_NOT_DECLARED:
      return std::string("Undeclared");
    /// Generally applied to fixtures
    case PRODUCT_DETAIL_ARC:
      return std::string("Arc");
    case PRODUCT_DETAIL_METAL_HALIDE:
      return std::string("Metal Halide");
    case PRODUCT_DETAIL_INCANDESCENT:
      return std::string("Incandescent");
    case PRODUCT_DETAIL_LED:
      return std::string("LED");
    case PRODUCT_DETAIL_FLUROESCENT:
      return std::string("Flouroescent");
    case PRODUCT_DETAIL_COLDCATHODE:
      return std::string("Cold Cathode");
    case PRODUCT_DETAIL_ELECTROLUMINESCENT:
      return std::string("Eloctroluminescent");
    case PRODUCT_DETAIL_LASER:
      return std::string("Laser");
    case PRODUCT_DETAIL_FLASHTUBE:
      return std::string("Flash Tube");
    /// Generally applied to fixture accessories
    case PRODUCT_DETAIL_COLORSCROLLER:
      return std::string("Color Scroll");
    case PRODUCT_DETAIL_COLORWHEEL:
      return std::string("Color Wheel");
    case PRODUCT_DETAIL_COLORCHANGE:
      return std::string("Color Change");
    case PRODUCT_DETAIL_IRIS_DOUSER:
      return std::string("Iris");
    case PRODUCT_DETAIL_DIMMING_SHUTTER:
      return std::string("Dimming Shutter");
    case PRODUCT_DETAIL_PROFILE_SHUTTER:
      return std::string("Profile Shutter");
    case PRODUCT_DETAIL_BARNDOOR_SHUTTER:
      return std::string("Barndoor");
    case PRODUCT_DETAIL_EFFECTS_DISC:
      return std::string("Effects Disc");
    case PRODUCT_DETAIL_GOBO_ROTATOR:
      return std::string("Gobo Rotator");
    /// Generally applied to Projectors
    case PRODUCT_DETAIL_VIDEO:
      return std::string("Video");
    case PRODUCT_DETAIL_SLIDE:
      return std::string("Slide");
    case PRODUCT_DETAIL_FILM:
      return std::string("Film");
    case PRODUCT_DETAIL_OILWHEEL:
      return std::string("Oil Wheel");
    case PRODUCT_DETAIL_LCDGATE:
      return std::string("LCD Gate");
    /// Generally applied to Atmospheric Effects
    case PRODUCT_DETAIL_FOGGER_GLYCOL:
      return std::string("Fogger (glycol)");
    case PRODUCT_DETAIL_FOGGER_MINERALOIL:
      return std::string("Fogger (mineral oil)");
    case PRODUCT_DETAIL_FOGGER_WATER:
      return std::string("Fogger (water)");
    case PRODUCT_DETAIL_C02:
      return std::string("Carbon Dioxide");
    case PRODUCT_DETAIL_LN2:
      return std::string("Liquid Nitrogen");
    case PRODUCT_DETAIL_BUBBLE:
      return std::string("Bubble");
    case PRODUCT_DETAIL_FLAME_PROPANE:
      return std::string("Flame (other)");
    case PRODUCT_DETAIL_FLAME_OTHER:
      return std::string("");
    case PRODUCT_DETAIL_OLEFACTORY_STIMULATOR:
      return std::string("Olefactory Stimulator");
    case PRODUCT_DETAIL_SNOW:
      return std::string("Snow");
    case PRODUCT_DETAIL_WATER_JET:
      return std::string("Water Jet");
    case PRODUCT_DETAIL_WIND:
      return std::string("Wind");
    case PRODUCT_DETAIL_CONFETTI:
      return std::string("Confetti");
    case PRODUCT_DETAIL_HAZARD:
      return std::string("Hazard");
    /// Generally applied to Dimmers/Power controllers
    case PRODUCT_DETAIL_PHASE_CONTROL:
      return std::string("Phase Control");
    case PRODUCT_DETAIL_REVERSE_PHASE_CONTROL:
      return std::string("Reverse Phase Control");
    case PRODUCT_DETAIL_SINE:
      return std::string("Sine");
    case PRODUCT_DETAIL_PWM:
      return std::string("PWM");
    case PRODUCT_DETAIL_DC:
      return std::string("DC");
    case PRODUCT_DETAIL_HFBALLAST:
      return std::string("High-Frequency Ballast");
    case PRODUCT_DETAIL_HFHV_NEONBALLAST:
      return std::string("High-Frequency/High-Voltage Neon");
    case PRODUCT_DETAIL_HFHV_EL:
      return std::string("High-Frequency/High-Voltage EL");
    case PRODUCT_DETAIL_MHR_BALLAST:
      return std::string("MHR Ballast");
    case PRODUCT_DETAIL_BITANGLE_MODULATION:
      return std::string("Bitangle Modulation");
    case PRODUCT_DETAIL_FREQUENCY_MODULATION:
      return std::string("Frequency Modulation");
    case PRODUCT_DETAIL_HIGHFREQUENCY_12V:
      return std::string("High Frequency 12v");
    case PRODUCT_DETAIL_RELAY_MECHANICAL:
      return std::string("Mechanical Relay");
    case PRODUCT_DETAIL_RELAY_ELECTRONIC:
      return std::string("Electronic Relay");
    case PRODUCT_DETAIL_SWITCH_ELECTRONIC:
      return std::string("Electronic Switch");
    case PRODUCT_DETAIL_CONTACTOR:
      return std::string("Contactor");
    /// Generally applied to Scenic drive
    case PRODUCT_DETAIL_MIRRORBALL_ROTATOR:
      return std::string("Mirroball Rotator");
    case PRODUCT_DETAIL_OTHER_ROTATOR:
      return std::string("Rotator (other)");
    case PRODUCT_DETAIL_KABUKI_DROP:
      return std::string("Kabuki Drop");
    case PRODUCT_DETAIL_CURTAIN:
      return std::string("Curtain");
    case PRODUCT_DETAIL_LINESET:
      return std::string("Lineset");
    case PRODUCT_DETAIL_MOTOR_CONTROL:
      return std::string("Motor Control");
    case PRODUCT_DETAIL_DAMPER_CONTROL:
      return std::string("Damper Control");
    /// Generally applied to Data Distribution
    case PRODUCT_DETAIL_SPLITTER:
      return std::string("Splitter");
    case PRODUCT_DETAIL_ETHERNET_NODE:
      return std::string("Ethernet Node");
    case PRODUCT_DETAIL_MERGE:
      return std::string("Merge");
    case PRODUCT_DETAIL_DATAPATCH:
      return std::string("Data Patch");
    case PRODUCT_DETAIL_WIRELESS_LINK:
      return std::string("Wireless Link");
    /// Generally applied to Data Conversion and Interfaces
    case PRODUCT_DETAIL_PROTOCOL_CONVERTOR:
      return std::string("Protocl Convertor");
    case PRODUCT_DETAIL_ANALOG_DEMULTIPLEX:
      return std::string("Analog De-multiplex");
    case PRODUCT_DETAIL_ANALOG_MULTIPLEX:
      return std::string("Analog Multiplex");
    case PRODUCT_DETAIL_SWITCH_PANEL:
      return std::string("Switch Panel");
    /// Generally applied to Audio or Video (AV) devices
    case PRODUCT_DETAIL_ROUTER:
      return std::string("Router");
    case PRODUCT_DETAIL_FADER:
      return std::string("Fader");
    case PRODUCT_DETAIL_MIXER:
      return std::string("Mixer");
    /// Generally applied to Controllers, Backup devices and Test Equipment
    case PRODUCT_DETAIL_CHANGEOVER_MANUAL:
      return std::string("Manual Changeover");
    case PRODUCT_DETAIL_CHANGEOVER_AUTO:
      return std::string("Auto Changeover");
    case PRODUCT_DETAIL_TEST:
      return std::string("TEST");
    /// Could be applied to any category
    case PRODUCT_DETAIL_GFI_RCD:
      return std::string("GFI RCD");
    case PRODUCT_DETAIL_BATTERY:
      return std::string("Battery");
    case PRODUCT_DETAIL_CONTROLLABLE_BREAKER:
      return std::string("Controllable Breaker");
    /// for where the Manufacturer believes that none of the defined details apply.
    case PRODUCT_DETAIL_OTHER:
      return std::string("Other");
    default:
      return std::string("Unknown");
    }
}


/**
 * @brief NackReasonDescription
 * @param NR
 * @return
 */
std::string NackReasonDescription(const uint16_t NR)
{
  switch (NR) {
    case NR_UNKNOWN_PID:
      return std::string("The responder cannot comply with request because the message is not implemented in responder.");
    case NR_FORMAT_ERROR:
      return std::string("The responder cannot interpret request as controller data was not formatted correctly.");
    case NR_HARDWARE_FAULT:
      return std::string("The responder cannot comply due to an internal hardware fault.");
    case NR_PROXY_REJECT:
      return std::string("Proxy is not the RDM line master and cannot comply with message.");
    case NR_WRITE_PROTECT:
      return std::string("SET Command normally allowed but being blocked currently.");
    case NR_UNSUPPORTED_COMMAND_CLASS:
      return std::string("Not valid for Command Class attempted.");
    case NR_DATA_OUT_OF_RANGE:
      return std::string("Value for given Parameter out of allowable range or not supported.");
    case NR_BUFFER_FULL:
      return std::string("Buffer or Queue space currently has no free space to store data.");
    case NR_PACKET_SIZE_UNSUPPORTED:
      return std::string("Incoming message exceeds buffer capacity.");
    case NR_SUB_DEVICE_OUT_OF_RANGE:
      return std::string("Sub-Device is out of range or unknown.");
    case NR_PROXY_BUFFER_FULL:
      return std::string("The proxy buffer is full and can not store any more Queued Message or Status Message responses.");
    case NR_ACTION_NOT_SUPPORTED:     //!< from E1.37-7
      return std::string("The specified action is not supported.");
    case NR_ENDPOINT_NUMBER_INVALID:  //!< from E1.37-7
      return std::string("The specified endpoint is invalid.");
    case NR_INVALID_ENDPOINT_MODE:    //!< from E1.37-7
      return std::string("The specified endpoint is in an invalid Endpoint Mode for the requested action.");
    case NR_UNKNOWN_UID:              //!< from E1.37-7
      return std::string("The specified UID is not recognized.");
    default:
      return std::string("Unknown");
    }
}


/**
 * @brief StatusMessageDescription
 * @param status
 * @return
 */
std::string StatusMessageDescription(uint16_t status)
{
  switch (status) {
    case STS_CAL_FAIL:
      return "%L failed calibration";
    case STS_SENS_NOT_FOUND:
      return "%L sensor not found";
    case STS_SENS_ALWAYS_ON:
      return "%L sensor always on";
    case STS_LAMP_DOUSED:
      return "Lamp doused";
    case STS_LAMP_STRIKE:
      return "Lamp failed to strike";
    case STS_OVERTEMP:
      return "Sensor %d over temp at %d degrees C";
    case STS_UNDERTEMP:
      return "Sensor %d under temp at %d degrees C";
    case STS_SENS_OUT_RANGE:
      return "Sensor %d out of range";
    case STS_OVERVOLTAGE_PHASE:
      return "Phase %d over voltage at %d V.";
    case STS_UNDERVOLTAGE_PHASE:
      return "Phase %d under voltage at %d V.";
    case STS_OVERCURRENT:
      return "Phase %d over current at %d A.";
    case STS_UNDERCURRENT:
      return "Phase %d under current at %d A.";
    case STS_PHASE:
      return "Phase %d is at %d degrees";
    case STS_PHASE_ERROR:
      return "Phase %d Error.";
    case STS_AMPS:
      return "%d Amps";
    case STS_VOLTS:
      return "%d Volts";
    case STS_DIMSLOT_OCCUPIED:
      return "No Dimmer";
    case STS_BREAKER_TRIP:
      return "Tripped Breaker";
    case STS_WATTS:
      return "%d Watts";
    case STS_DIM_FAILURE:
      return "Dimmer Failure";
    case STS_DIM_PANIC:
      return "Panic Mode";
    case STS_READY:
      return "%L ready";
    case STS_NOT_READY:
      return "%L not ready";
    case STS_LOW_FLUID:
      return "%L low fluid";
    default:
      return std::string();
    }
}

} // namespace RDM
