#include "map_settings.h"

#include <QDebug>

#include "selfdrive/common/util.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/request_repeater.h"
#include "selfdrive/ui/qt/widgets/controls.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"

static QString shorten(const QString &str, int max_len) {
  return str.size() > max_len ? str.left(max_len).trimmed() + "…" : str;
}

MapPanel::MapPanel(QWidget* parent) : QWidget(parent) {
  stack = new QStackedWidget;

  QWidget * main_widget = new QWidget;
  QVBoxLayout *main_layout = new QVBoxLayout(main_widget);
  const int icon_size = 200;

  // Home
  QHBoxLayout *home_layout = new QHBoxLayout;
  home_button = new QPushButton;
  home_button->setIconSize(QSize(icon_size, icon_size));
  home_layout->addWidget(home_button);

  home_address = new QLabel;
  home_address->setWordWrap(true);
  home_layout->addSpacing(30);
  home_layout->addWidget(home_address);
  home_layout->addStretch();

  // Work
  QHBoxLayout *work_layout = new QHBoxLayout;
  work_button = new QPushButton;
  work_button->setIconSize(QSize(icon_size, icon_size));
  work_layout->addWidget(work_button);

  work_address = new QLabel;
  work_address->setWordWrap(true);
  work_layout->addSpacing(30);
  work_layout->addWidget(work_address);
  work_layout->addStretch();

  // Home & Work layout
  QHBoxLayout *home_work_layout = new QHBoxLayout;
  home_work_layout->addLayout(home_layout, 1);
  home_work_layout->addSpacing(50);
  home_work_layout->addLayout(work_layout, 1);

  main_layout->addLayout(home_work_layout);
  main_layout->addSpacing(20);
  main_layout->addWidget(horizontal_line());
  main_layout->addSpacing(20);

  // Current route
  {
    current_widget = new QWidget(this);
    QVBoxLayout *current_layout = new QVBoxLayout(current_widget);

    QLabel *title = new QLabel("Current Destination");
    title->setStyleSheet("font-size: 55px");
    current_layout->addWidget(title);

    current_route = new ButtonControl("", "CLEAR");
    current_route->setStyleSheet("padding-left: 40px;");
    current_layout->addWidget(current_route);
    QObject::connect(current_route, &ButtonControl::clicked, [=]() {
      params.remove("NavDestination");
      updateCurrentRoute();
    });

    current_layout->addSpacing(10);
    current_layout->addWidget(horizontal_line());
    current_layout->addSpacing(20);
  }
  main_layout->addWidget(current_widget);

  // Recents
  QLabel *recents_title = new QLabel("Recent Destinations");
  recents_title->setStyleSheet("font-size: 55px");
  main_layout->addWidget(recents_title);
  main_layout->addSpacing(20);

  recent_layout = new QVBoxLayout;
  QWidget *recent_widget = new LayoutWidget(recent_layout, this);
  ScrollView *recent_scroller = new ScrollView(recent_widget, this);
  main_layout->addWidget(recent_scroller);

  // No prime upsell
  QWidget * no_prime_widget = new QWidget;
  {
    QVBoxLayout *no_prime_layout = new QVBoxLayout(no_prime_widget);
    QLabel *signup_header = new QLabel("Try the Navigation Beta");
    signup_header->setStyleSheet(R"(font-size: 75px; color: white; font-weight:600;)");
    signup_header->setAlignment(Qt::AlignCenter);

    no_prime_layout->addWidget(signup_header);
    no_prime_layout->addSpacing(50);

    QLabel *screenshot = new QLabel;
    QPixmap pm = QPixmap("../assets/navigation/screenshot.png");
    screenshot->setPixmap(pm.scaledToWidth(1080, Qt::SmoothTransformation));
    no_prime_layout->addWidget(screenshot, 0, Qt::AlignHCenter);

    QLabel *signup = new QLabel("Get turn-by-turn directions displayed and more with a comma \nprime subscription. Sign up now: https://connect.comma.ai");
    signup->setStyleSheet(R"(font-size: 45px; color: white; font-weight:300;)");
    signup->setAlignment(Qt::AlignCenter);

    no_prime_layout->addSpacing(20);
    no_prime_layout->addWidget(signup);
    no_prime_layout->addStretch();
  }

  stack->addWidget(main_widget);
  stack->addWidget(no_prime_widget);
  stack->setCurrentIndex(uiState()->prime_type ? 0 : 1);

  QVBoxLayout *wrapper = new QVBoxLayout(this);
  wrapper->addWidget(stack);


  clear();

  if (auto dongle_id = getDongleId()) {
    // Fetch favorite and recent locations
    {
      QString url = CommaApi::BASE_URL + "/v1/navigation/" + *dongle_id + "/locations";
      RequestRepeater* repeater = new RequestRepeater(this, url, "ApiCache_NavDestinations", 30, true);
      QObject::connect(repeater, &RequestRepeater::requestDone, this, &MapPanel::parseResponse);
    }

    // Destination set while offline
    {
      QString url = CommaApi::BASE_URL + "/v1/navigation/" + *dongle_id + "/next";
      RequestRepeater* repeater = new RequestRepeater(this, url, "", 10, true);
      HttpRequest* deleter = new HttpRequest(this);

      QObject::connect(repeater, &RequestRepeater::requestDone, [=](const QString &resp, bool success) {
        if (success && resp != "null") {
          if (params.get("NavDestination").empty()) {
            qWarning() << "Setting NavDestination from /next" << resp;
            params.put("NavDestination", resp.toStdString());
          } else {
            qWarning() << "Got location from /next, but NavDestination already set";
          }

          // Send DELETE to clear destination server side
          deleter->sendRequest(url, HttpRequest::Method::DELETE);
        }
      });
    }
  }
}

void MapPanel::showEvent(QShowEvent *event) {
  updateCurrentRoute();
}

void MapPanel::clear() {
  home_button->setIcon(QPixmap("../assets/navigation/home_inactive.png"));
  home_address->setStyleSheet(R"(font-size: 50px; color: grey;)");
  home_address->setText("No home\nlocation set");
  home_button->disconnect();

  work_button->setIcon(QPixmap("../assets/navigation/work_inactive.png"));
  work_address->setStyleSheet(R"(font-size: 50px; color: grey;)");
  work_address->setText("No work\nlocation set");
  work_button->disconnect();

  clearLayout(recent_layout);
}

void MapPanel::updateCurrentRoute() {
  auto dest = QString::fromStdString(params.get("NavDestination"));
  QJsonDocument doc = QJsonDocument::fromJson(dest.trimmed().toUtf8());
  if (dest.size() && !doc.isNull()) {
    auto name = doc["place_name"].toString();
    auto details = doc["place_details"].toString();
    current_route->setTitle(shorten(name + " " + details, 42));
  }
  current_widget->setVisible(dest.size() && !doc.isNull());
}

void MapPanel::parseResponse(const QString &response, bool success) {
  stack->setCurrentIndex((uiState()->prime_type || success) ? 0 : 1);

  if (!success) {
    return;
  }

  QJsonDocument doc = QJsonDocument::fromJson(response.trimmed().toUtf8());
  if (doc.isNull()) {
    qDebug() << "JSON Parse failed on navigation locations";
    return;
  }

  clear();

  bool has_recents = false;
  for (auto &save_type: {"favorite", "recent"}) {
    for (auto location : doc.array()) {
      auto obj = location.toObject();

      auto type = obj["save_type"].toString();
      auto label = obj["label"].toString();
      auto name = obj["place_name"].toString();
      auto details = obj["place_details"].toString();

      if (type != save_type) continue;

      if (type == "favorite" && label == "home") {
        home_address->setText(name);
        home_address->setStyleSheet(R"(font-size: 50px; color: white;)");
        home_button->setIcon(QPixmap("../assets/navigation/home.png"));
        QObject::connect(home_button, &QPushButton::clicked, [=]() {
          navigateTo(obj);
          emit closeSettings();
        });
      } else if (type == "favorite" && label == "work") {
        work_address->setText(name);
        work_address->setStyleSheet(R"(font-size: 50px; color: white;)");
        work_button->setIcon(QPixmap("../assets/navigation/work.png"));
        QObject::connect(work_button, &QPushButton::clicked, [=]() {
          navigateTo(obj);
          emit closeSettings();
        });
      } else {
        ClickableWidget *widget = new ClickableWidget;
        QHBoxLayout *layout = new QHBoxLayout(widget);
        layout->setContentsMargins(15, 14, 40, 14);

        QLabel *star = new QLabel("★");
        auto sp = star->sizePolicy();
        sp.setRetainSizeWhenHidden(true);
        star->setSizePolicy(sp);

        star->setVisible(type == "favorite");
        star->setStyleSheet(R"(font-size: 60px;)");
        layout->addWidget(star);
        layout->addSpacing(10);


        QLabel *recent_label = new QLabel(shorten(name + " " + details, 45));
        recent_label->setStyleSheet(R"(font-size: 50px;)");

        layout->addWidget(recent_label);
        layout->addStretch();

        QLabel *arrow = new QLabel("→");
        arrow->setStyleSheet(R"(font-size: 60px;)");
        layout->addWidget(arrow);

        widget->setStyleSheet(R"(
          .ClickableWidget {
            border-radius: 10px;
            border-width: 1px;
            border-style: solid;
            border-color: gray;
          }
          QWidget {
            background-color: #393939;
            color: #9c9c9c;
          }
        )");

        QObject::connect(widget, &ClickableWidget::clicked, [=]() {
          navigateTo(obj);
          emit closeSettings();
        });

        recent_layout->addWidget(widget);
        recent_layout->addSpacing(10);
        has_recents = true;
      }
    }

  }

  if (!has_recents) {
    QLabel *no_recents = new QLabel("no recent destinations");
    no_recents->setStyleSheet(R"(font-size: 50px; color: #9c9c9c)");
    recent_layout->addWidget(no_recents);
  }

  recent_layout->addStretch();
  repaint();
}

void MapPanel::navigateTo(const QJsonObject &place) {
  QJsonDocument doc(place);
  params.put("NavDestination", doc.toJson().toStdString());
}
