// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "analyzer.hpp"
#include "bargraph.hpp"
#include "main.hpp"
#include "menu.hpp"
#include "sensorhelper.hpp"

#include <ncurses.h>

#include <string>
#include <vector>
constexpr int MARGIN_BOTTOM = 1;
class DBusTopWindow
{
  public:
    DBusTopWindow()
    {
        win = newwin(25, 80, 0, 0); // Default to 80x25, will be updated
        has_border_ = true;
        focused_ = false;
        selectable_ = true;
        visible_ = true;
        maximize_ = false;
    }

    virtual ~DBusTopWindow() {}
    virtual void OnKeyDown(const std::string& key) = 0;
    virtual void Render() = 0;
    virtual void OnResize(int win_w, int win_h) = 0;
    void UpdateWindowSizeAndPosition()
    {
        mvwin(win, rect.y, rect.x);
        wresize(win, rect.h, rect.w);
    }

    void DrawBorderIfNeeded()
    {
        if (focused_)
        {
            wborder(win, '*', '*', '*', '*', '*', '*', '*', '*');
        }
        else
        {
            wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
        }
        wrefresh(win);
    }

    virtual void RecreateWindow()
    {
        delwin(win);
        win = newwin(25, 80, 0, 0);
        UpdateWindowSizeAndPosition();
    }

    virtual std::string GetStatusString() = 0;
    WINDOW* win;
    Rect rect;
    bool has_border_;
    bool focused_;
    bool selectable_;
    bool maximize_;
    bool visible_;
};

class SummaryView : public DBusTopWindow
{
  public:
    SummaryView() : DBusTopWindow() {}
    void Render() override;
    void OnResize(int win_w, [[maybe_unused]] int win_h) override
    {
        rect.h = 8;
        rect.w = win_w;
        rect.x = 0;
        rect.y = 0;
        UpdateWindowSizeAndPosition();
    }

    void UpdateDBusTopStatistics(DBusTopStatistics* stat);
    void OnKeyDown([[maybe_unused]] const std::string& key) override {}
    std::string GetStatusString() override
    {
        return "Summary View";
    }

  private:
    float method_call_, method_return_, signal_, error_, total_;
};

class SensorDetailView : public DBusTopWindow
{
  public:
    SensorDetailView() : DBusTopWindow()
    {
        choice_ = -999; // -999 means invalid
        h_padding = 2;
        h_spacing = 3;
        col_width = 15;
        idx0 = idx1 = -999;
        state = SensorList;
    }

    void Render() override;
    int DispSensorsPerColumn()
    {
        return rect.h - 3;
    }

    int DispSensorsPerRow()
    {
        int ncols = 0;
        while (true)
        {
            int next = ncols + 1;
            int w = 2 * h_padding + col_width * next;
            if (next > 1)
                w += (next - 1) * h_spacing;
            if (w <= rect.w - 2)
            {
                ncols = next;
            }
            else
            {
                break;
            }
        }
        return ncols;
    }

    void OnKeyDown(const std::string& key) override
    {
        if (state == SensorList)
        { // Currently in sensor list
            if (key == "right")
            {
                MoveChoiceCursorHorizontally(1);
            }
            else if (key == "left")
            {
                MoveChoiceCursorHorizontally(-1);
            }
            else if (key == "up")
            {
                MoveChoiceCursor(-1, true);
            }
            else if (key == "down")
            {
                MoveChoiceCursor(1, true);
            }
            else if (key == "enter")
            {
                if (choice_ != -999)
                {
                    state = SensorDetail;
                }
            }
            else if (key == "escape")
            {
                choice_ = -999;
            }
        }
        else if (state == SensorDetail)
        { // Currently focusing on a sensor
            if (key == "right" || key == "down")
            {
                MoveChoiceCursor(1, true);
            }
            else if (key == "left" || key == "up")
            {
                MoveChoiceCursor(-1, true);
            }
            else if (key == "escape")
            {
                state = SensorList;
            }
        }

        Render(); // This window is already on top, redrawing won't corrupt
    }

    void MoveChoiceCursor(int delta, bool wrap_around = true)
    {
        const int ns = sensor_ids_.size();
        if (ns < 1)
            return;
        // First of all, if cursor is inactive, activate it
        if (choice_ == -999)
        {
            if (delta > 0)
            {
                choice_ = 0;
                curr_sensor_id_ = sensor_ids_[0];
                return;
            }
            else
            {
                choice_ = ns - 1;
                curr_sensor_id_ = sensor_ids_.back();
                return;
            }
        }
        int choice_next = choice_ + delta;
        while (choice_next >= ns)
        {
            if (wrap_around)
            {
                choice_next -= ns;
            }
            else
            {
                choice_next = ns - 1;
            }
        }
        while (choice_next < 0)
        {
            if (wrap_around)
            {
                choice_next += ns;
            }
            else
            {
                choice_next = 0;
            }
        }
        choice_ = choice_next;
        curr_sensor_id_ = sensor_ids_[choice_];
    }

    void MoveChoiceCursorHorizontally(int delta)
    {
        if (delta != 0 && delta != -1 && delta != 1)
            return;
        const int ns = sensor_ids_.size();
        if (ns < 1)
            return;
        if (choice_ == -999)
        {
            if (delta > 0)
            {
                choice_ = 0;
                curr_sensor_id_ = sensor_ids_[0];
                return;
            }
            else
            {
                curr_sensor_id_ = sensor_ids_.back();
                choice_ = ns - 1;
                return;
            }
        }
        const int nrows = DispSensorsPerColumn();
        int tot_columns = (ns - 1) / nrows + 1;
        int num_rows_last_column = ns - nrows * (tot_columns - 1);
        int y = choice_ % nrows, x = choice_ / nrows;
        if (delta == 1)
        {
            x++;
        }
        else
        {
            x--;
        }
        bool overflow_to_right = false;
        if (y < num_rows_last_column)
        {
            if (x >= tot_columns)
            {
                overflow_to_right = true;
            }
        }
        else
        {
            if (x >= tot_columns - 1)
            {
                overflow_to_right = true;
            }
        }
        bool overflow_to_left = false;
        if (x < 0)
        {
            overflow_to_left = true;
        }
        {
            if (overflow_to_right)
            {
                y++;
                // overflow past the right of window
                // Start probing next line
                if (y >= nrows)
                {
                    choice_ = 0;
                    return;
                }
                else
                {
                    choice_ = y;
                    return;
                }
            }
            else if (overflow_to_left)
            { // overflow past the left of window
                y--;
                if (y < 0)
                { // overflow past the top of window
                    // Focus on the visually bottom-right entry
                    if (num_rows_last_column == nrows)
                    { // last col fully populated
                        choice_ = ns - 1;
                    }
                    else
                    { // last column is not fully populated
                        choice_ = ns - num_rows_last_column - 1;
                    }
                    return;
                }
                else
                {
                    if (y < num_rows_last_column)
                    {
                        choice_ = nrows * (tot_columns - 1) + y;
                    }
                    else
                    {
                        choice_ = nrows * (tot_columns - 2) + y;
                    }
                }
            }
            else
            {
                choice_ = y + x * nrows;
            }
        }
        curr_sensor_id_ = sensor_ids_[choice_];
    }

    // Cache the sensor list in the sensor snapshot
    void UpdateSensorSnapshot(SensorSnapshot* snapshot)
    {
        std::string old_sensor_id = "";
        if (choice_ != -999)
        {
            old_sensor_id = sensor_ids_[choice_];
        }
        std::vector<std::string> new_sensors =
            snapshot->GetDistinctSensorNames();
        if (new_sensors == sensor_ids_)
        {
            return; // Nothing is changed
        }
        // Assume changed
        sensor_ids_ = new_sensors;
        choice_ = -999;
        for (int i = 0; i < static_cast<int>(new_sensors.size()); i++)
        {
            if (new_sensors[i] == old_sensor_id)
            {
                choice_ = i;
                break;
                curr_sensor_id_ = sensor_ids_[choice_];
            }
        }
    }

    void OnResize(int win_w, int win_h) override
    {
        rect.x = 0;
        rect.y = 8 - MARGIN_BOTTOM;
        rect.w = win_w / 2;
        rect.h = win_h - rect.y - MARGIN_BOTTOM;
        UpdateWindowSizeAndPosition();
    }

    std::vector<std::string> sensor_ids_;
    // We need to keep track of the currently-selected sensor ID because
    // the sensor ID might theoretically become invalidated at any moment, and
    // we should allow the UI to show an error gracefully in that case.
    std::string curr_sensor_id_;
    int choice_;
    int h_padding;
    int h_spacing;
    int col_width;
    int idx0, idx1; // Range of sensors on display
    enum State
    {
        SensorList,
        SensorDetail,
    };

    State state;
    std::string GetStatusString() override;
};

class DBusStatListView : public DBusTopWindow
{
  public:
    DBusStatListView();
    void Render() override;
    void OnResize(int win_w, int win_h) override;
    void OnKeyDown(const std::string& key) override;
    int horizontal_pan_;
    int menu_h_, menu_w_, menu_margin_;
    ArrowKeyNavigationMenu* menu1_;
    ArrowKeyNavigationMenu* menu2_;
    int highlight_col_idx_; // Currently highlighted column
    int row_idx_;           // Currently highlighted row

    int sort_col_idx_; // Column used for sorting
    enum SortOrder
    {
        Ascending,
        Descending,
    };
    SortOrder sort_order_;

    int disp_row_idx_;    // From which row to start displaying? (essentially a
                          // vertical scroll bar)
    int last_choices_[2]; // Last choice index on either side
    enum MenuState
    {
        Hidden,
        LeftSide,  // When the user is choosing an entry on the left side
        RightSide, // When the user is choosing an entry on the right side
    };

    std::vector<DBusTopSortField> GetSortFields();
    MenuState curr_menu_state_, last_menu_state_;
    std::string GetStatusString() override;
    void RecreateWindow()
    {
        delwin(win);
        win = newwin(25, 80, 0, 0);
        menu1_->win_ = win;
        menu2_->win_ = win;
        UpdateWindowSizeAndPosition();
    }

  private:
    void SetMenuState(MenuState s)
    {
        last_menu_state_ = curr_menu_state_;
        // Moving out from a certain side: save the last choice of that side
        switch (curr_menu_state_)
        {
            case LeftSide:
                if (s == RightSide)
                {
                    last_choices_[0] = menu1_->Choice();
                    menu1_->Deselect();
                }
                break;
            case RightSide:
                if (s == LeftSide)
                {
                    last_choices_[1] = menu2_->Choice();
                    menu2_->Deselect();
                }
                break;
            default:
                break;
        }
        // Moving into a certain side: save the cursor
        switch (s)
        {
            case LeftSide:
                if (!menu1_->Empty())
                {
                    menu1_->SetChoiceAndConstrain(last_choices_[0]);
                }
                break;
            case RightSide:
                if (!menu2_->Empty())
                {
                    menu2_->SetChoiceAndConstrain(last_choices_[1]);
                }
                break;
            default:
                break;
        }
        curr_menu_state_ = s;
    }
    void PanViewportOrMoveHighlightedColumn(const int delta_x);
    // ColumnHeaders and ColumnWidths are the actual column widths used for
    // display. They are "msg/s" or "I2c/s" prepended to the chosen set of
    // fields.
    std::vector<std::string> ColumnHeaders();
    std::vector<int> ColumnWidths();
    // X span, for checking visibility
    std::pair<int, int> GetXSpanForColumn(const int col_idx);
    bool IsXSpanVisible(const std::pair<int, int>& xs,
                        const int tolerance); // uses horizontal_pan_
    std::vector<std::string> visible_columns_;
    std::unordered_map<std::string, int> column_widths_;
    std::map<std::vector<std::string>, DBusTopComputedMetrics> stats_snapshot_;
};

class FooterView : public DBusTopWindow
{
  public:
    FooterView() : DBusTopWindow()
    {
        selectable_ = false; // Cannot be selected by the tab key
    }

    void OnKeyDown([[maybe_unused]] const std::string& key) override {}
    void OnResize(int win_w, int win_h) override
    {
        rect.h = 1;
        rect.w = win_w;
        rect.x = 0;
        rect.y = win_h - 1;
        UpdateWindowSizeAndPosition();
    }

    void Render() override;
    std::string GetStatusString() override
    {
        return "";
    }
};
