#include "vgui_askconnectpanel.h"

#include "cl_pluginhelpers.h"
#include "inputsystem/ButtonCode.h"
#include "keys.h"
#include "mathlib/mathlib.h"
#include "vgui/ILocalize.h"
#include "vgui/IVGui.h"
#include "vgui_baseui_interface.h"
#include "vgui_controls/AnimationController.h"
#include "vgui_controls/Frame.h"
#include "vgui_controls/Label.h"

using namespace vgui;

class CAskConnectPanel : public EditablePanel {
  DECLARE_CLASS_SIMPLE(CAskConnectPanel, vgui::EditablePanel);

 public:
  CAskConnectPanel(VPANEL parent);
  ~CAskConnectPanel();

  void GetHostName(char *pOut, int maxOutBytes);
  void SetHostName(const char *pHostName);
  void StartSlideAnimation(float flDuration);
  void UpdateCurrentPosition();
  void Hide();

  virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
  virtual void ApplySettings(KeyValues *inResourceData);
  virtual void OnTick();

 public:
  static CAskConnectPanel *s_pAskConnectPanel;

 private:
  char m_HostName[256];
  Color m_bgColor;
  int m_OriginalWidth;  

  double m_flAnimationEndTime;  

  Label *m_pInfoLabel;

  Label *m_pHostNameLabel;
  int m_HostNameLabelRightSidePadding;  

  Label *m_pAcceptLabel;
  AnimationController *m_pAnimationController;
};

CAskConnectPanel *CAskConnectPanel::s_pAskConnectPanel = NULL;

CAskConnectPanel::CAskConnectPanel(VPANEL parent)
    : BaseClass(NULL, "AskConnectPanel"), m_bgColor(0, 0, 0, 192) {
  SetParent(parent);
  Assert(s_pAskConnectPanel == NULL);
  s_pAskConnectPanel = this;
  m_flAnimationEndTime = -1;

  SetKeyBoardInputEnabled(false);
  SetMouseInputEnabled(false);
  SetVisible(false);

  m_pHostNameLabel = new Label(this, "HostNameLabel", "");
  m_pAcceptLabel = new Label(this, "AcceptLabel", "");
  m_pInfoLabel = new Label(this, "InfoLabel", "");

  m_HostName[0] = 0;
  vgui::ivgui()->AddTickSignal(GetVPanel());
  SetAutoDelete(true);

  m_pAnimationController = new vgui::AnimationController(NULL);
  m_pAnimationController->SetParent(parent);
  m_pAnimationController->SetScriptFile(parent,
                                        "scripts/plugin_animations.txt");
  m_pAnimationController->SetProportional(false);

  LoadControlSettings("resource\\askconnectpanel.res");
  InvalidateLayout(true);

  m_OriginalWidth = GetWide();
  int x, y, wide, tall;
  m_pHostNameLabel->GetBounds(x, y, wide, tall);
  m_HostNameLabelRightSidePadding = GetWide() - (x + wide);
}

CAskConnectPanel::~CAskConnectPanel() { s_pAskConnectPanel = NULL; }

void CAskConnectPanel::GetHostName(char *pOut, int maxOutBytes) {
  V_strncpy(pOut, m_HostName, maxOutBytes);
}

void CAskConnectPanel::SetHostName(const char *pHostName) {
  V_strncpy(m_HostName, pHostName, sizeof(m_HostName));
  m_pHostNameLabel->SetText(pHostName);

  int x, y, wide, tall;
  m_pHostNameLabel->SizeToContents();
  m_pHostNameLabel->GetBounds(x, y, wide, tall);

  int x2, y2, wide2, tall2;
  wchar_t wcMessage[512];
  g_pVGuiLocalize->ConstructString(
      wcMessage, sizeof(wcMessage),
      g_pVGuiLocalize->Find("#Valve_ServerOfferingToConnect"), 0);
  m_pInfoLabel->SetText(wcMessage);
  m_pInfoLabel->SizeToContents();
  m_pInfoLabel->GetBounds(x2, y2, wide2, tall2);

  int desiredWidth =
      std::max(x + wide, x2 + wide2) + m_HostNameLabelRightSidePadding;
  if (desiredWidth < m_OriginalWidth) desiredWidth = m_OriginalWidth;

  SetWide(desiredWidth);
}

void CAskConnectPanel::ApplySettings(KeyValues *inResourceData) {
  BaseClass::ApplySettings(inResourceData);

  const char *pStr = inResourceData->GetString("BgColor", NULL);
  if (pStr) {
    int r, g, b, a;
    if (sscanf_s(pStr, "%d %d %d %d", &r, &g, &b, &a) == 4) {
      m_bgColor = Color(r, g, b, a);
      SetBgColor(m_bgColor);
    }
  }
}

void CAskConnectPanel::StartSlideAnimation(float flDuration) {
  m_flAnimationEndTime = Plat_FloatTime() + flDuration;

  const char *pKeyName = Key_NameForBinding("askconnect_accept");
  if (pKeyName) {
    wchar_t wcKeyName[64], wcMessage[512];
    g_pVGuiLocalize->ConvertANSIToUnicode(pKeyName, wcKeyName,
                                          sizeof(wcKeyName));
    g_pVGuiLocalize->ConstructString(
        wcMessage, sizeof(wcMessage),
        g_pVGuiLocalize->Find("#Valve_PressKeyToAccept"), 1, wcKeyName);
    m_pAcceptLabel->SetText(wcMessage);
  } else {
    m_pAcceptLabel->SetText("#Valve_BindKeyToAccept");
  }

  m_pAnimationController->StartAnimationSequence("AskConnectShow");
  SetVisible(true);
  InvalidateLayout();
  UpdateCurrentPosition();
}

void CAskConnectPanel::Hide() {
  m_flAnimationEndTime = -1;
  SetVisible(false);
}

void CAskConnectPanel::OnTick() {

  if (m_flAnimationEndTime != -1) {
    if (Plat_FloatTime() > m_flAnimationEndTime) {
      m_flAnimationEndTime = -1;
      m_pAnimationController->StartAnimationSequence("AskConnectHide");
    }
  }

  m_pAnimationController->UpdateAnimations(Plat_FloatTime());

  if (GetAlpha() == 0) SetVisible(false);

  if (IsVisible()) {
    UpdateCurrentPosition();
  }

  BaseClass::OnTick();
}

void CAskConnectPanel::UpdateCurrentPosition() {
  int x = 0, y = 0, wide = 0, tall = 0;
  if (g_PluginManager) g_PluginManager->GetHudMessagePosition(x, y, wide, tall);

  SetPos(x, y + tall);
}

void CAskConnectPanel::ApplySchemeSettings(vgui::IScheme *pScheme) {
  BaseClass::ApplySchemeSettings(pScheme);

  SetBgColor(m_bgColor);
  SetPaintBackgroundType(2);
}

void SetupDefaultAskConnectAcceptKey() {

  if (!Key_NameForBinding("askconnect_accept")) {

    if (!Key_BindingForKey(KEY_F3)) {
      Key_SetBinding(KEY_F3, "askconnect_accept");
    }
  }
}

vgui::Panel *CreateAskConnectPanel(VPANEL parent) {
  return new CAskConnectPanel(parent);
}

void ShowAskConnectPanel(const char *pHostName, float flDuration) {
  CAskConnectPanel *pPanel = CAskConnectPanel::s_pAskConnectPanel;
  if (pPanel) {
    pPanel->SetHostName(pHostName);
    pPanel->StartSlideAnimation(flDuration);
    pPanel->MoveToFront();
  }
}

void HideAskConnectPanel() {
  CAskConnectPanel *pPanel = CAskConnectPanel::s_pAskConnectPanel;
  if (pPanel) pPanel->Hide();
}

bool IsAskConnectPanelActive(char *pHostName, int maxHostNameBytes) {
  CAskConnectPanel *pPanel = CAskConnectPanel::s_pAskConnectPanel;
  if (pPanel && pPanel->IsVisible() && pPanel->GetAlpha() > 0) {
    pPanel->GetHostName(pHostName, maxHostNameBytes);
    return true;
  }

  return false;
}
// Copyright © 1996-2018, Valve Corporation, All rights reserved.

#include "vgui_askconnectpanel.h"

#include "cl_pluginhelpers.h"
#include "inputsystem/ButtonCode.h"
#include "keys.h"
#include "mathlib/mathlib.h"
#include "vgui/ILocalize.h"
#include "vgui/IVGui.h"
#include "vgui_baseui_interface.h"
#include "vgui_controls/AnimationController.h"
#include "vgui_controls/Frame.h"
#include "vgui_controls/Label.h"

using namespace vgui;

class CAskConnectPanel : public EditablePanel {
  DECLARE_CLASS_SIMPLE(CAskConnectPanel, vgui::EditablePanel);

 public:
  CAskConnectPanel(VPANEL parent);
  ~CAskConnectPanel();

  void GetHostName(char *pOut, int maxOutBytes);
  void SetHostName(const char *pHostName);
  void StartSlideAnimation(float flDuration);
  void UpdateCurrentPosition();
  void Hide();

  virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
  virtual void ApplySettings(KeyValues *inResourceData);
  virtual void OnTick();

 public:
  static CAskConnectPanel *s_pAskConnectPanel;

 private:
  char m_HostName[256];
  Color m_bgColor;
  int m_OriginalWidth;  // Don't get less than this wide.

  double m_flAnimationEndTime;  // -1 if not playing

  Label *m_pInfoLabel;

  Label *m_pHostNameLabel;
  int m_HostNameLabelRightSidePadding;  // Grow the whole panel to make sure
                                        // there's this much padding on the
                                        // right of the hostname label.

  Label *m_pAcceptLabel;
  AnimationController *m_pAnimationController;
};

CAskConnectPanel *CAskConnectPanel::s_pAskConnectPanel = NULL;

CAskConnectPanel::CAskConnectPanel(VPANEL parent)
    : BaseClass(NULL, "AskConnectPanel"), m_bgColor(0, 0, 0, 192) {
  SetParent(parent);
  Assert(s_pAskConnectPanel == NULL);
  s_pAskConnectPanel = this;
  m_flAnimationEndTime = -1;

  SetKeyBoardInputEnabled(false);
  SetMouseInputEnabled(false);
  SetVisible(false);

  m_pHostNameLabel = new Label(this, "HostNameLabel", "");
  m_pAcceptLabel = new Label(this, "AcceptLabel", "");
  m_pInfoLabel = new Label(this, "InfoLabel", "");

  m_HostName[0] = 0;
  vgui::ivgui()->AddTickSignal(GetVPanel());
  SetAutoDelete(true);

  m_pAnimationController = new vgui::AnimationController(NULL);
  m_pAnimationController->SetParent(parent);
  m_pAnimationController->SetScriptFile(parent,
                                        "scripts/plugin_animations.txt");
  m_pAnimationController->SetProportional(false);

  LoadControlSettings("resource\\askconnectpanel.res");
  InvalidateLayout(true);

  m_OriginalWidth = GetWide();
  int x, y, wide, tall;
  m_pHostNameLabel->GetBounds(x, y, wide, tall);
  m_HostNameLabelRightSidePadding = GetWide() - (x + wide);
}

CAskConnectPanel::~CAskConnectPanel() { s_pAskConnectPanel = NULL; }

void CAskConnectPanel::GetHostName(char *pOut, int maxOutBytes) {
  V_strncpy(pOut, m_HostName, maxOutBytes);
}

void CAskConnectPanel::SetHostName(const char *pHostName) {
  V_strncpy(m_HostName, pHostName, sizeof(m_HostName));
  m_pHostNameLabel->SetText(pHostName);

  // Update our width.
  int x, y, wide, tall;
  m_pHostNameLabel->SizeToContents();
  m_pHostNameLabel->GetBounds(x, y, wide, tall);

  int x2, y2, wide2, tall2;
  wchar_t wcMessage[512];
  g_pVGuiLocalize->ConstructString(
      wcMessage, sizeof(wcMessage),
      g_pVGuiLocalize->Find("#Valve_ServerOfferingToConnect"), 0);
  m_pInfoLabel->SetText(wcMessage);
  m_pInfoLabel->SizeToContents();
  m_pInfoLabel->GetBounds(x2, y2, wide2, tall2);

  int desiredWidth =
      std::max(x + wide, x2 + wide2) + m_HostNameLabelRightSidePadding;
  if (desiredWidth < m_OriginalWidth) desiredWidth = m_OriginalWidth;

  SetWide(desiredWidth);
}

void CAskConnectPanel::ApplySettings(KeyValues *inResourceData) {
  BaseClass::ApplySettings(inResourceData);

  const char *pStr = inResourceData->GetString("BgColor", NULL);
  if (pStr) {
    int r, g, b, a;
    if (sscanf_s(pStr, "%d %d %d %d", &r, &g, &b, &a) == 4) {
      m_bgColor = Color(r, g, b, a);
      SetBgColor(m_bgColor);
    }
  }
}

void CAskConnectPanel::StartSlideAnimation(float flDuration) {
  m_flAnimationEndTime = Plat_FloatTime() + flDuration;

  // Figure out what key they have bound...
  const char *pKeyName = Key_NameForBinding("askconnect_accept");
  if (pKeyName) {
    wchar_t wcKeyName[64], wcMessage[512];
    g_pVGuiLocalize->ConvertANSIToUnicode(pKeyName, wcKeyName,
                                          sizeof(wcKeyName));
    g_pVGuiLocalize->ConstructString(
        wcMessage, sizeof(wcMessage),
        g_pVGuiLocalize->Find("#Valve_PressKeyToAccept"), 1, wcKeyName);
    m_pAcceptLabel->SetText(wcMessage);
  } else {
    m_pAcceptLabel->SetText("#Valve_BindKeyToAccept");
  }

  m_pAnimationController->StartAnimationSequence("AskConnectShow");
  SetVisible(true);
  InvalidateLayout();
  UpdateCurrentPosition();
}

void CAskConnectPanel::Hide() {
  m_flAnimationEndTime = -1;
  SetVisible(false);
}

void CAskConnectPanel::OnTick() {
  // Do the hide animation?
  if (m_flAnimationEndTime != -1) {
    if (Plat_FloatTime() > m_flAnimationEndTime) {
      m_flAnimationEndTime = -1;
      m_pAnimationController->StartAnimationSequence("AskConnectHide");
    }
  }

  m_pAnimationController->UpdateAnimations(Plat_FloatTime());

  // Make sure vgui doesn't call Paint() on us after we're hidden.
  if (GetAlpha() == 0) SetVisible(false);

  if (IsVisible()) {
    UpdateCurrentPosition();
  }

  BaseClass::OnTick();
}

void CAskConnectPanel::UpdateCurrentPosition() {
  int x = 0, y = 0, wide = 0, tall = 0;
  if (g_PluginManager) g_PluginManager->GetHudMessagePosition(x, y, wide, tall);

  SetPos(x, y + tall);
}

void CAskConnectPanel::ApplySchemeSettings(vgui::IScheme *pScheme) {
  BaseClass::ApplySchemeSettings(pScheme);

  SetBgColor(m_bgColor);
  SetPaintBackgroundType(2);
}

void SetupDefaultAskConnectAcceptKey() {
  // If they don't have a binding for askconnect_accept, set one up.
  if (!Key_NameForBinding("askconnect_accept")) {
    // .. but only if they don't already have something setup for F3.
    if (!Key_BindingForKey(KEY_F3)) {
      Key_SetBinding(KEY_F3, "askconnect_accept");
    }
  }
}

vgui::Panel *CreateAskConnectPanel(VPANEL parent) {
  return new CAskConnectPanel(parent);
}

void ShowAskConnectPanel(const char *pHostName, float flDuration) {
  CAskConnectPanel *pPanel = CAskConnectPanel::s_pAskConnectPanel;
  if (pPanel) {
    pPanel->SetHostName(pHostName);
    pPanel->StartSlideAnimation(flDuration);
    pPanel->MoveToFront();
  }
}

void HideAskConnectPanel() {
  CAskConnectPanel *pPanel = CAskConnectPanel::s_pAskConnectPanel;
  if (pPanel) pPanel->Hide();
}

bool IsAskConnectPanelActive(char *pHostName, int maxHostNameBytes) {
  CAskConnectPanel *pPanel = CAskConnectPanel::s_pAskConnectPanel;
  if (pPanel && pPanel->IsVisible() && pPanel->GetAlpha() > 0) {
    pPanel->GetHostName(pHostName, maxHostNameBytes);
    return true;
  }

  return false;
}
