/*
;    Project:       ESP GLCD SOLAR MONITOR
;    Date:          3rd Sep 2022
;
;    (C) 2022       Carsten Schmiemann
;
; 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 <logger.h>
#include <Wire.h>
#include <U8g2lib.h>

#include <display.h>
#include <lang.h>
#include <screens.h>
#include <pins.h>

//U8G2_SSD1306_128X64_VCOMH0_F_HW_I2C display(U8G2_R0, OLED_RST, OLED_SCL, OLED_SDA); OLED on TTGO
U8G2_ST7920_128X64_F_HW_SPI display(U8G2_R2, LCD_CS, U8X8_PIN_NONE);
//U8G2_ST7920_128X64_F_2ND_HW_SPI display(U8G2_R2, LCD_CS, U8X8_PIN_NONE);
//U8G2_ST7920_128X64_F_SW_SPI display(U8G2_R2, LCD_E_SCLK, LCD_RW_SI, LCD_CS, U8X8_PIN_NONE); 

char* title_pv;
char* title_battery;
char* title_grid;
char* title_graph;
char* title_graph_load;
char* title_graph_pv;

bool pv_charging = false;
bool show_temp_outside;
bool show_time_display;
bool show_pv_chg_screen;
bool show_graph_screen;
bool show_stats_screen;

int time_hour;
int time_minute;
float temperature_outside;
char* screenbuffer;

void display_setup(char lang[2], bool show_temp, bool show_time, bool dc_pv_charger, bool show_graph, bool show_stats) {
    show_temp_outside = show_temp;
    show_time_display = show_time;
    show_pv_chg_screen = dc_pv_charger;
    show_graph_screen = show_graph;
    show_stats_screen = show_stats;
    set_display_language(lang);
}

void display_temp_outside(float mqtt_temp_outside) {
    temperature_outside = mqtt_temp_outside;
}

void display_time(int hour, int minute) {
    time_hour = hour;
    time_minute = minute;
}

void display_begin() {
    display.begin();
}

void display_init(char* VERSION) {
    display.firstPage();
    do {
        display_logo();
        display.drawStr(0,52,"by Carsten Schmiemann");
        display.drawStr(20,60, "(C) 2022");
        display.drawStr(76,60, VERSION);
    } while ( display.nextPage() );
}

void display_logo() {
    display.setFont(u8g2_font_10x20_tr);
    display.drawStr(0,20,"PV Monitor");
    display.drawStr(48,35,"Project");
    display.setFont(u8g2_font_6x10_tr);
}

void display_logo_small() {
    display.setFont(u8g2_font_6x10_tr);
    display.drawStr(10,7,"PV Monitor Project");
    display.drawLine(0, 10, 128, 10);
}

void display_text(char* TEXT1, char* TEXT2) {
    display.firstPage();
    do {
        display_logo();
        display.drawStr(0,52, TEXT1);
        display.drawStr(0,60, TEXT2);
    } while ( display.nextPage() );
}

void display_text_fullscreen(char* TEXT1, char* TEXT2, char* TEXT3, char* TEXT4, char* TEXT5, char* TEXT6) {
    display.firstPage();
    do {
        display_logo_small();
        display.drawStr(0,20, TEXT1);
        display.drawStr(0,28, TEXT2);
        display.drawStr(0,36, TEXT3);
        display.drawStr(0,44, TEXT4);
        display.drawStr(0,52, TEXT5);
        display.drawStr(0,60, TEXT6);
    } while ( display.nextPage() );
}

void display_header(char* TEXT) {
    display.setFont(u8g2_font_6x10_tr);
    display.drawStr(2,7,TEXT);
    display.drawLine(0, 8, 128, 8);

    if (show_time_display)
    {
        display.drawLine(94, 0, 94, 8);
        display.setCursor(97,7); 
        if (time_hour < 10) {
            display.print("0");
        }
        display.print(time_hour); display.print(":");
        if (time_minute < 10) {
            display.print("0");
        }
        display.print(time_minute);

        if (show_temp_outside)
        {
            display.drawLine(58, 0, 58, 8);
            if (temperature_outside < 10)
            {
                display.setCursor(68,7); 
            }
            else
            {
                display.setCursor(62,7);
            }
            display.print(temperature_outside,1); display.print("C");
        }
    }
    else if (show_temp_outside)
    {
        display.drawLine(93, 0, 93, 8);
        if (temperature_outside < 10)
            {
                display.setCursor(103,7); 
            }
            else
            {
                display.setCursor(97,7);
            }
            display.print(temperature_outside,1); display.print("C");
    }
}

//PV Charger
void display_screen_pv(float pv_voltage, float pv_wattage, float battery_voltage, float pv_amps, float pv_kwh)
{
    logPrintlnD("Refresh PV_Charger display values...");
    display.firstPage();
        do {
            display_header(title_pv);
            display.drawXBM(0,9, Solarpanel_width, Solarpanel_height, Solarpanel_bits);
            display.setCursor(72,18); display.print(pv_voltage); display.print("V");
            display.setCursor(72,28); display.print(pv_wattage,0); display.print("W");
            display.setCursor(72,38); display.print(pv_kwh); display.print("kWh");
            display.setCursor(72,54); display.print(battery_voltage); display.print("V");
            display.setCursor(72,63); display.print(pv_amps); display.print("A");       
        } while ( display.nextPage() );
}

//Battery
void display_screen_battery(float battery_voltage, float battery_amps, float battery_wattage, float battery_soc, float batt_cell_v_min, float batt_cell_v_max)
{
    logPrintlnD("Refresh Battery display values...");
    display.firstPage();
        do {
            display_header(title_battery);
            display.drawXBM(7,9, battery_width, battery_height, battery_bits);
            display.drawFrame(5,38,40,26);
            display.drawStr(46,45,"F");
            display.drawStr(46,64,"E");
            display.setCursor(11,60); display.print(batt_cell_v_min); display.print("V");
            display.setCursor(11,50); display.print(batt_cell_v_max); display.print("V");
            display.setCursor(72,18); display.print(battery_voltage); display.print("V");
            display.setCursor(72,28); display.print(battery_amps,1); display.print("A");
            display.setCursor(72,38); display.print(battery_wattage,0); display.print("W");
            display.setFont(u8g2_font_inr19_mf);
            if (battery_soc == 100)
            {
                display.setCursor(60,63);
            }
            else
            {
                display.setCursor(70,63);
            }
            display.print(battery_soc,0); display.print("%");
            display.setFont(u8g2_font_6x10_tr);
            int batt_fill_y = map(battery_soc, 0, 100, 62, 38);
            int batt_fill_height = map(battery_soc, 0, 100, 0, 24);
            display.setDrawColor(2);
            display.drawBox(6,batt_fill_y,38,batt_fill_height);
        } while ( display.nextPage() );
}

//Grid
void display_screen_grid(float grid_power, float consum, float inv_power, float inv_current, float pv_wattage)
{
    logPrintlnD("Refresh Grid display values...");
    display.firstPage();
        do {
            display_header(title_grid);
            display.drawXBM(0,9, grid_width, grid_height, grid_bits);
            display.setCursor(10,45); display.print(grid_power,0); display.print("W");
            display.setCursor(40,54); display.print(inv_power,0); display.print("W");
            display.setCursor(40,63); display.print(inv_current,1); display.print("A");
            display.setCursor(87,20); display.print(consum,0); display.print("W");

            if (show_pv_chg_screen)
            {
                display.setCursor(101,38); display.print(pv_wattage,0); display.print("W");
                int pv_chg_y_pos;
                if (pv_wattage >= 10) {
                    if (pv_charging)
                    {
                        pv_chg_y_pos = 45;
                        pv_charging = false;
                    }
                    else 
                    {
                        pv_chg_y_pos = 47;
                        pv_charging = true;
                    }
                    display.drawXBM(89,pv_chg_y_pos, down_pv_width, down_pv_height, down_pv_bits);
                }
            }
        } while ( display.nextPage() );

}

//Display graph screen
void display_screen_graph(float *values, char* key, int type, int buffersize)
{
    logPrintlnD("Display graph...");
    display.firstPage();
        do {
            display_header(title_graph);
            if (type == 0)
            {
                display.drawStr(58,17, title_graph_load);
            }
            else if (type == 1)
            {
                display.drawStr(58,17, title_graph_pv);
            }
            display.drawLine(17, 60, 9, 60); //X mark
            display.drawLine(15, 10, 15, 62); //Y boarder
            display.drawStr(7,63, "0");
            display.drawStr(7,34, "k");
            display.drawStr(7,46, "W");
            display.drawLine(13, 36, 15, 36); //marker Y 5
            display.drawLine(13, 13, 15, 13); //marker Y 1

            for (int i = 25; i<130; i += 10)
            {
                display.drawLine(i, 60, i, 62); //marker X
            }

            // Auto-scale graph (scale 1kW to 24kW automatically)
            float max = values[0];
            // find highest value
            for (int i = 0; i<buffersize; i++)
            {
                if (max < values[i])
                {
                    max = values[i];
                }
            }
            int graph_max_kW = 1000;
            if (max > 1000) { graph_max_kW = 2000; }
            if (max > 2000) { graph_max_kW = 3000; }
            if (max > 3000) { graph_max_kW = 4000; }
            if (max > 4000) { graph_max_kW = 5000; }
            if (max > 5000) { graph_max_kW = 6000; }
            if (max > 6000) { graph_max_kW = 7000; }
            if (max > 7000) { graph_max_kW = 8000; }
            if (max > 8000) { graph_max_kW = 9000; }
            if (max > 9000) { graph_max_kW = 10000; }
            if (max > 10000) { graph_max_kW = 11000; }
            if (max > 11000) { graph_max_kW = 12000; }
            if (max > 12000) { graph_max_kW = 13000; }
            if (max > 13000) { graph_max_kW = 14000; }
            if (max > 14000) { graph_max_kW = 15000; }
            if (max > 15000) { graph_max_kW = 16000; }
            if (max > 16000) { graph_max_kW = 17000; }
            if (max > 17000) { graph_max_kW = 18000; }
            if (max > 18000) { graph_max_kW = 19000; }
            if (max > 19000) { graph_max_kW = 20000; }
            if (max > 20000) { graph_max_kW = 21000; }
            if (max > 21000) { graph_max_kW = 22000; }
            if (max > 22000) { graph_max_kW = 23000; }
            if (max > 23000) { graph_max_kW = 24000; }

            if ((graph_max_kW/1000) < 10)
            {
                display.setCursor(7,17);
            }
            else 
            {
                display.setCursor(1,17);
            }
            display.print(graph_max_kW/1000);

            for (int i = 0; i<buffersize; i++)
            {
                display.drawLine((16+i), 60, (16+i), map(values[i], 0, graph_max_kW, 60, 13));
            }

            if (strlen(key) < 3) {
                display.drawStr(117, 17, key);
            }
            else
            {
                display.drawStr(111, 17, key);
            }
            
        } while ( display.nextPage() );
}