#pragma once
#include "Widget.h"
#include "rtc.h"
#include "../fonts/DS_DIGI42pt7b_mono.h"




class ClockWidget : public Widget {
    
private:
    uint32_t _lastUpdate = 0;
    bool _forceDraw = false, _positionsCalculated = false;
    
    // Predefiniowane pozycje
    int16_t _clockX = 0;
    int16_t _clockY = 0;
    int16_t _infoX = 0;
    int16_t _dayY = 0;
    int16_t _lineY = 0;
    int16_t _dateY = 0;
    int16_t _yearY = 0;
	int16_t _textX = 0;
	int16_t _textY = 0;
    
    // Wymiary
    uint16_t _clockWidth = 0;
    uint16_t _clockHeight = 0;
    uint16_t _dayHeight = 0;
    uint16_t _dateHeight = 0;
	
	const GFXfont* clockFont = &DS_DIGI42pt7b;
	const GFXfont* wdayFont = &FreeSansBold12pt7b;
	const GFXfont* dateFont = &FreeSans9pt7b;
	const GFXfont* textFont = &FreeMonoBold9pt7b;

    char _buffer[6];
    bool _blinkState = false;
    
    bool updateTime( char* buff, uint8_t size, tm* tout = nullptr ) {
        struct tm t;
        
			if( rtc.getLocalTimeFromRTC( &t ) == RTCState::NOTINIT  ) return false;
        
			if( tout ) *tout = t;
        
        _blinkState ^= 1;
        snprintf( buff, size, "%02d%c%02d",
                t.tm_hour,
                _blinkState ? ':' : ' ',
                t.tm_min );
        
        return true;
    }
    
    void daymonth( tm* t, char* buff, uint8_t size ) {
        snprintf( buff, size, "%02d/%02d",
                  t->tm_mday,
                  t->tm_mon + 1 );
    }
    
    void year( tm* t, char* buff, uint8_t size ) {
        snprintf( buff, size, "%04d",
                  t->tm_year + 1900 );
    }
    
	const char* getWeekDay( tm* t ) {
		const char* weekDays[] = { "Nd.", "Pn.", "Wt.", "Sr.", "Cz.", "Pt.", "So." };
		const uint8_t daysCount = sizeof(weekDays) / sizeof(weekDays[0]);

			if( t == nullptr || t->tm_wday < 0 || t->tm_wday >= daysCount ) {
				return "Err";
			}
			
		return weekDays[t->tm_wday];
	}
    
    void calculatePositions() {
        
			if( !_dsp ) return;

        int16_t x1 = 0, y1 = 0;
		uint16_t tempW = 0, tempH = 0;
        // 1. ZEGAR - czcionka 42pt (sprawdzona, mieści się)
        _dsp->setFont( clockFont );
        _dsp->getTextBounds( "88:88", 0, 0, &x1, &y1, &_clockWidth, &_clockHeight );
        // Zegar: 20px od lewej krawędzi
        _clockX = _x + 20;
        // Wyśrodkowanie w pionie
        _clockY = _y + (_h - _clockHeight) / 2 - y1;
        // 2. Prawa sekcja - 20px odstępu od zegara
        _infoX = _clockX + _clockWidth + 20;
        // 3. DZIEŃ TYGODNIA - pogrubiona 12pt
        _dsp->setFont( wdayFont );
        _dsp->getTextBounds( "WT", 0, 0, &x1, &y1, &tempW, &_dayHeight );
        // Dzień tygodnia: 2px od góry
        _dayY = _y + 2 - y1;
        // 4. LINIA - 6px odstępu po dniu tygodnia
        _lineY = _y + 2 + _dayHeight + 4;
        // 5. DATA - 12pt
        _dsp->setFont( dateFont );
        _dsp->getTextBounds( "88/88", 0, 0, &x1, &y1, &tempW, &_dateHeight );
        // Data: 6px odstępu po linii
        _dateY = _lineY + 6 - y1;
        // 6. ROK - 10pt (4px odstępu po dacie)
        _yearY = _dateY + _dateHeight + 4;
		
		//7. NOTINIT (komunikat o braku iniclaizacji modułu RTC)
		_dsp->setFont( textFont );
		_dsp->getTextBounds( rtc.getStateText( RTCState::NOTINIT ), 0, 0, &x1, &y1, &tempW, &tempH );
		_textX = _x + ((_w - tempW) / 2)-2;
		_textY = _y + (_h - tempH) / 2 - y1;
    }
    
public:
    void init( MyDisplay* dsp, int16_t x=0, int16_t y=0, uint16_t w=0, uint16_t h=0 ) {
		
			if( !dsp ) return;

			if( w == 0 ) w = dsp->getDisplayWidth();
			
			if( h == 0 ) h = dsp->getDisplayHeight();
        
        Widget::init( dsp, x, y, w, h );
        _initialized = true;
    }
    
    void reposition() {
        calculatePositions();
        _forceDraw = true;
    }
    
    virtual void draw( void ) override {
        
			if( !_dsp || !_initialized ) return;
        
        uint32_t now = millis();
        
			if( now - _lastUpdate >= 750 || _forceDraw ) {
				struct tm dt;
			
				_dsp->setClipping( _x, _y, _w, _h );
				_dsp->fillRect( _x, _y, _w, _h, _scr_color );
				
					if( !_positionsCalculated ){
						calculatePositions();
						_positionsCalculated = true;
					}
					
				auto state = rtc.getLocalTimeFromRTC( &dt );
				
					if( state == RTCState::NOTINIT ){
						_dsp->setFont( textFont );
						_dsp->setTextColor( 15 );
						_dsp->setCursor( _textX, _textY );
						_dsp->print( rtc.getStateText( RTCState::NOTINIT ) );						
					} else {
						//========== 1. ZEGAR ==========
						updateTime( _buffer, sizeof(_buffer), &dt );
						
							if( _blinkState || state == RTCState::OK ){
								_dsp->setFont( clockFont );
								_dsp->setTextColor( 15 );
								_dsp->setCursor( _clockX, _clockY );
								_dsp->print( _buffer );
							}

							if( state == RTCState::OK ){
								//DZIEŃ TYGODNIA
								_dsp->setFont( wdayFont );
								_dsp->setTextColor( 15 );
								_dsp->setCursor( _infoX, _dayY );
								_dsp->print( getWeekDay( &dt ) );
								//LINIA
								int16_t lineWidth = _x + _w - _infoX - 8;
								_dsp->fillRect( _infoX, _lineY, lineWidth, 3, 15 );
								//DATA
								daymonth( &dt, _buffer, sizeof(_buffer) );
								_dsp->setFont( dateFont );
								_dsp->setTextColor( 7 );
								_dsp->setCursor( _infoX, _dateY );
								_dsp->print( _buffer );
								//ROK
								year( &dt, _buffer, sizeof(_buffer) );
								_dsp->setFont( dateFont );
								_dsp->setTextColor( 7 );
								_dsp->setCursor( _infoX, _yearY );
								_dsp->print( _buffer );
							}
					}
				
				_dsp->clearClipping();
				_lastUpdate = now;
				_forceDraw = false;
			}
    }
    
    virtual void redraw( void ) override {
        _forceDraw = true;
    }
};