<?php


namespace ColibriWP\PageBuilder\License;


use ColibriWP\PageBuilder\PageBuilder;
use function ExtendBuilder\array_get_value;

class Updater {

    private static $instance = null;

    private $product_data = null;
    private $path         = null;

    public function __construct( $path ) {
        if ( is_admin() ) {
            $this->path = $path;
            if ( $this->canCheckForUpdates() ) {
                add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'checkForUpdate' ) );
            }
            add_filter( 'plugins_api', array( $this, 'pluginsApiHandler' ), 10, 3 );
        }
    }

    public function canCheckForUpdates() {
        if ( PageBuilder::instance()->isPRO() ) {
            return true;
        }

        $data = apply_filters( 'colibri_page_builder/companion/update_remote_data', array(
            'url'  => '',
            'args' => [
                'product' => 'colibri-page-builder'
            ],
        ), $this );

        if ( $plugin = array_get_value( $data, 'args.product', false ) ) {
            if ( $plugin === 'colibri-page-builder-pro' ) {
                return true;
            }
        }
    }

    public static function load( $path ) {

        if ( ! self::$instance ) {
            self::$instance = new static( $path );
        }

        return static::getInstance();
    }

    /**
     * @return Updater|null
     */
    public static function getInstance() {


        return self::$instance;
    }

    public function checkForUpdate( $transient ) {
        $has_custom_update_endpoint = apply_filters( 'colibri_page_builder/custom_update_endpoint', false );

        if ( empty( $transient->checked ) ) {
            return $transient;
        }

        if ( ! $has_custom_update_endpoint ) {
            return $transient;
        }

        $info = $this->isUpdateAvailable();

        if ( $info !== false ) {
            $transient = $this->addTransientData( $transient, $info );
        }


        return $transient;

    }

    public function isUpdateAvailable() {
        $status = $this->getRemoteInfo();
        if ( $status ) {
            if ( version_compare( $status->version, $this->getLocalVersion(), '>' ) ) {
                return $status;
            }
        }

        return false;
    }

    public function getRemoteInfo() {
        $data = apply_filters( 'colibri_page_builder/companion/update_remote_data', array(
            'url'  => '',
            'args' => [
                'product' => 'colibri-page-builder'
            ]
        ), $this );

        $data = array_merge( array(
            'url'  => '',
            'args' => []
        ), (array) $data );

        $url  = $data['url'];
        $args = apply_filters( 'colibri_page_builder/endpoints/request_body', $data['args'] );

        if ( ! $url ) {
            return false;
        }

        $url = add_query_arg( $args, $url );

        $response = wp_remote_get( $url, array(
            'timeout'    => 10,
            'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ),
            'sslverify'  => false,
        ) );

        if ( is_wp_error( $response ) ) {
            return false;
        }

        $response_body = wp_remote_retrieve_body( $response );
        $result        = json_decode( $response_body );

        if ( ! $result || ! $result->status || $result->status !== "success" ) {
            return false;
        }

        $result = array_merge( array(
            'name'            => '',
            'description'     => '',
            'version'         => '',
            'tested'          => '',
            'author'          => '',
            'last_updated'    => '',
            'banner_low'      => '',
            'banner_high'     => '',
            'package_url'     => '',
            'description_url' => '',
            'icons'           => [],
            'requires'        => ''
        ), (array) $result->body );

        $product_data = $this->getProductData();

        if ( ! $result['description'] ) {
            $result['description'] = array_get_value( $product_data, 'Description', '' );
        }

        if ( ! $result['author'] ) {
            $result['author'] = array_get_value( $product_data, 'Author', '' );
        }

        return (object) $result;
    }

    public function getProductData() {
        if ( ! $this->product_data ) {

            $path = $this->path;

            $data = apply_filters( 'colibri_page_builder/companion/update_remote_data', array(
                'url'  => '',
                'args' => [
                    'product' => 'colibri-page-builder'
                ]
            ), $this );

            $path = array_get_value( $data, 'plugin_path', $path );

            $this->product_data = get_plugin_data( $path, false );
        }

        return $this->product_data;
    }

    public function getLocalVersion() {
        $data = $this->getProductData();

        return $data['Version'];
    }

    public function addTransientData( $transient, $info ) {
        $plugin_slug = plugin_basename( $this->path );

        $transient->response[ $plugin_slug ] = (object) array(
            'new_version' => $info->version,
            'package'     => $info->package_url,
            'icons'       => (array) $info->icons,
            'slug'        => $plugin_slug,
            'tested'      => $info->tested
        );

        return $transient;
    }

    /**
     * A function for the WordPress "plugins_api" filter. Checks if
     * the user is requesting information about the current plugin and returns
     * its details if needed.
     *
     * This function is called before the Plugins API checks
     * for plugin information on WordPress.org.
     *
     * @param $res      bool|object The result object, or false (= default value).
     * @param $action   string      The Plugins API action. We're interested in 'plugin_information'.
     * @param $args     array       The Plugins API parameters.
     *
     * @return bool|object
     */
    public function pluginsApiHandler( $res, $action, $args ) {
        if ( $action == 'plugin_information' ) {
            if ( isset( $args->slug ) && $args->slug == plugin_basename( $this->path ) ) {
                $info = $this->getRemoteInfo();

                if ( ! $info ) {
                    return $res;
                }

                $res = (object) array(
                    'name'          => $info->name,
                    'version'       => $info->version,
                    'slug'          => $args->slug,
                    'download_link' => $info->package_url,

                    'tested'       => $info->tested,
                    'requires'     => $info->requires,
                    'last_updated' => $info->last_updated,
                    'homepage'     => $info->description_url,

                    'sections' => array(
                        'description' => $info->description,
                    ),

                    'banners' => array(
                        'low'  => $info->banner_low,
                        'high' => $info->banner_high,
                    ),

                    'external' => true
                );

                // Add change log tab if the server sent it
                if ( isset( $info->changelog ) ) {
                    $res['sections']['changelog'] = $info->changelog;
                }

                return $res;
            }
        }

        return false;
    }


}

