<?php

namespace Blazemedia\Affiliation\Rendering;

use Blazemedia\Affiliation\Rendering\Utils\LinksDataInPage;
use Blazemedia\Affiliation\Utils\HttpRequest;
use Blazemedia\Affiliation\Utils\ParseLinkLookUpTable;
use Blazemedia\Affiliation\Utils\TimeTracker;

abstract class RenderingTemplate {

    protected PageData $pageData;
    
    protected string $url;
    protected string $program;
    protected string $format;
    protected string $format_id;
    protected array $extra = [];

    protected Disclaimer $disclaimer;
    
    protected TimeTracker $timeTracker;

    protected ParseLinkLookUpTable $linkLookUp;
    
    protected array|null $links;
    protected string|null $markup;


    public function __construct( string $shortcode = '', string $format = '', string $format_id = '' ) {

        $this->timeTracker = TimeTracker::getInstance();
        $this->linkLookUp = ParseLinkLookUpTable::getInstance();

        $this->disclaimer = Disclaimer::getInstance();

        $this->pageData = new PageData;
        
        $this->format    = $format;
        $this->format_id = $format_id;

        /// rileva il link nel testo
        add_shortcode( $shortcode,  [ $this, 'manageFormat'] );
    }


    /**
     * Si attiva quando viene richiamato un formato
     *
     * @param [type] $atts
     * @param [type] $content
     * @param [type] $tag
     * @return string
     */
    public function manageFormat( $atts, $content, $tag ) : string {

        /// se è presente un formato attiva la stampa del disclaimer
        $this->disclaimer->setStatus( true );

        // $markup = $this->getMetaMarkup( $tag, $atts, )

        return $this->manageLink( $atts, $content, $tag );
        //return $this->getFormatMarkup( $atts, $content, $tag );

    }

/*
    public function getFormatMarkup() {

        $markup = getStoredFormatMarkup();
        if( )


        return $this->manageLink( $atts, $content, $tag );
    }*/

    
    /**
     * Stampa il bottone impostato da shortcode
     */
    public function manageLink( $atts, $content, $tag ) {
        $params = $this->pageData->getParams([
            
            'format'     => $this->format,
            'format_id'  => isset( $atts['format_id'] ) ? $atts['format_id'] : 0,
            'link_id'    => $atts['link_id'],
            'extra'      => urlencode( json_encode( $this->extra ) )
        ]);

        $this->getFormatData( $params );

        /// richiede il markup del link
        return str_replace( '{cta}', $content, $this->markup );
    }
    

    
    function getTransientKey( array $params ) {

        $key = "{$params['post_id']}_{$params['format']}";

        switch( $params['format'] ){

            case 'parse'    :
            case 'parsebtn' :
            case 'price'    :
                $link = json_decode( urldecode($params['extra']) )->link;

                $this->linkLookUp = ParseLinkLookUpTable::getInstance();
                $link_id = $this->linkLookUp->getLinkId( $link );

                return "gt_{$key}_lookup_{$link_id}";

            case 'table'  :                  
            case 'widget' :
                return "gt_{$key}_{$params['format_id']}";

            case 'link'   :  
            case 'button' :  
                return "gt_{$key}_{$params['link_id']}";
                
            
            default: 
                return '';
        }
    }

    protected function printApiCallForDebug( $params, $apiCall ) {

        $show_api_call = isset($_GET['print-apicall'] ) ? $_GET['print-apicall'] : '';

        if( is_user_logged_in() && $show_api_call != '' ) {

            if( $params['format'] == $show_api_call ){

                echo "<a href='{$apiCall}'>API CALL - {$params['format']}</a>"; die;
            }
        }
    }
    

    function doCall( array $params, $curl = true, $timeout = 2 ) : array {

        $apiCall = BLZ_API_RENDERING_MANAGER .'render/'. array_reduce( array_keys( $params ), function( $urlpart, $key ) use( $params ){

            return "{$urlpart}{$params[$key]}/";

        } , '');

        $this->printApiCallForDebug( $params, $apiCall );

        $response = json_decode( HttpRequest::getContent( $apiCall, $curl, $timeout ), true );

        $program_codes = [];
        $subjects      = [];
        $themes        = [];

        if( isset( $response['linkvars'] )) {

            $program_codes = is_array($response['linkvars']['program_codes'] ) ? $response['linkvars']['program_codes'] : [];
            $subjects      = is_array($response['linkvars']['subjects'] ) ? $response['linkvars']['subjects'] : [];
            $themes        = is_array($response['linkvars']['themes'] ) ? $response['linkvars']['themes'] : [];
        
        } else {

            if(is_user_logged_in() && $response != null ) {

                echo "<pre style='color:white;background:red'>{$params['format']} {$params['format_id']} - no linkvars - response : ";
                var_dump($response);
                echo "</pre>";
            }
        }

        $linksData = LinksDataInPage::getInstance();

        $linksData->addPrograms( $program_codes );
        $linksData->addSubjects( $subjects );
        $linksData->addThemes( $themes );

        return $response == null ? [] : $response;
    }


    private function isBadResult( $data ) {

        return isset( $data['status'] ) && $data['status'] == 'error';
    }


    function getCachedData( array $params, $hours = 24 ) {

        // $this->timeTracker = TimeTracker::getInstance();
        // $this->timeTracker->setStartTime();

        if( BLAZE_AFFILIATION_CACHE ){

            $transientKey = $this->getTransientKey( $params );

            if( $transientKey !== '' ) {

                $data = get_transient( $transientKey );

                if( $data === false ) {
                    
                    $data = $this->doCallWithAttempts( $params );

                    if( !$this->isBadResult( $data ) ) {

                        set_transient( $transientKey, $data, 3600 * $hours );
                    }
                    
                    // $this->timeTracker->setEndTime();

                    // Logger::write( "{$this->timeTracker->getMSInterval()},NO_TRANSIENT_{$transientKey}_{$params['post_id']}_{$params['format']}\n" );
                } else {

                    // $this->timeTracker->setEndTime();

                    // Logger::write( "{$this->timeTracker->getMSInterval()},OK_TRANSIENT_{$transientKey}_{$params['post_id']}_{$params['format']}\n" );        
                }

                return $data;
            }
        } 

        $data = $this->doCallWithAttempts( $params );

        // $this->timeTracker->setEndTime();

        // Logger::write( "{$this->timeTracker->getMSInterval()},NO_CACHE_{$params['post_id']}_{$params['format']}\n" );

        return $data;
    }


    function doCallWithAttempts( $params ) {

        $data = $this->doCall( $params );

        $timeout = 2;

        while( $timeout < 10 && $this->isBadResult( $data ) ) {

            //sleep for 0,2 seconds
            usleep( 200000 );

            $timeout += 2;

            $data = $this->doCall( $params, true, $timeout );
        }

        return $data;
    }
    



    /**
     * Fill the markup with actual data
     *
     * @return string
     */
    function getFormatData( array $params ) : void {

        $extra = json_decode(urldecode($params['extra']),true);
        $extra['path'] = urlencode($this->pageData->getPermalink());
        $params['extra'] = urlencode(json_encode($extra));

        $data = $this->getCachedData( $params );

        $this->markup = isset( $data['markup']   ) ? $data['markup']   : '';
        $this->links  = isset( $data['linkvars'] ) ? $data['linkvars'] : [];

        $this->disclaimer->add( isset( $data['disclaimer'] ) ? $data['disclaimer'] : '' ) ;
        
    }

}
