// Copyright 2010 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <cstring>

#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteEmu/Attachment/Turntable.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"

namespace WiimoteEmu
{
static const u8 turntable_id[] = {0x03, 0x00, 0xa4, 0x20, 0x01, 0x03};

static const u16 turntable_button_bitmasks[] = {
    Turntable::BUTTON_L_GREEN, Turntable::BUTTON_L_RED, Turntable::BUTTON_L_BLUE,
    Turntable::BUTTON_R_GREEN, Turntable::BUTTON_R_RED, Turntable::BUTTON_R_BLUE,
    Turntable::BUTTON_MINUS,   Turntable::BUTTON_PLUS,  Turntable::BUTTON_EUPHORIA,
};

static const char* const turntable_button_names[] = {
    _trans("Green Left"),
    _trans("Red Left"),
    _trans("Blue Left"),
    _trans("Green Right"),
    _trans("Red Right"),
    _trans("Blue Right"),
    "-",
    "+",
    _trans("Euphoria"),
};

Turntable::Turntable(WiimoteEmu::ExtensionReg& _reg) : Attachment(_trans("Turntable"), _reg)
{
  // buttons
  groups.emplace_back(m_buttons = new Buttons("Buttons"));
  for (auto& turntable_button_name : turntable_button_names)
    m_buttons->controls.emplace_back(new ControlGroup::Input(turntable_button_name));

  // turntables
  groups.emplace_back(m_left_table = new Slider(_trans("Table Left")));
  groups.emplace_back(m_right_table = new Slider(_trans("Table Right")));

  // stick
  groups.emplace_back(m_stick = new AnalogStick("Stick", DEFAULT_ATTACHMENT_STICK_RADIUS));

  // effect dial
  groups.emplace_back(m_effect_dial = new Triggers(_trans("Effect")));
  m_effect_dial->controls.emplace_back(new ControlGroup::Input(_trans("Dial")));

  // crossfade
  groups.emplace_back(m_crossfade = new Slider(_trans("Crossfade")));

  // set up register
  // id
  memcpy(&id, turntable_id, sizeof(turntable_id));
}

void Turntable::GetState(u8* const data)
{
  wm_turntable_extension* const ttdata = (wm_turntable_extension*)data;
  ttdata->bt = 0;

  // stick
  {
    ControlState x, y;
    m_stick->GetState(&x, &y);

    ttdata->sx = static_cast<u8>((x * 0x1F) + 0x20);
    ttdata->sy = static_cast<u8>((y * 0x1F) + 0x20);
  }

  // left table
  {
    ControlState tt;
    s8 tt_;
    m_left_table->GetState(&tt);

    tt_ = static_cast<s8>(tt * 0x1F);

    ttdata->ltable1 = tt_;
    ttdata->ltable2 = tt_ >> 5;
  }

  // right table
  {
    ControlState tt;
    s8 tt_;
    m_right_table->GetState(&tt);

    tt_ = static_cast<s8>(tt * 0x1F);

    ttdata->rtable1 = tt_;
    ttdata->rtable2 = tt_ >> 1;
    ttdata->rtable3 = tt_ >> 3;
    ttdata->rtable4 = tt_ >> 5;
  }

  // effect dial
  {
    ControlState dial;
    u8 dial_;
    m_effect_dial->GetState(&dial);

    dial_ = static_cast<u8>(dial * 0x0F);

    ttdata->dial1 = dial_;
    ttdata->dial2 = dial_ >> 3;
  }

  // crossfade slider
  {
    ControlState cfs;
    m_crossfade->GetState(&cfs);

    ttdata->slider = static_cast<u8>((cfs * 0x07) + 0x08);
  }

  // buttons
  m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks);

  // flip button bits :/
  ttdata->bt ^= (BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE | BUTTON_R_GREEN | BUTTON_R_RED |
                 BUTTON_R_BLUE | BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA);
}

bool Turntable::IsButtonPressed() const
{
  u16 buttons = 0;
  m_buttons->GetState(&buttons, turntable_button_bitmasks);
  return buttons != 0;
}
}
