<?php
final class spbsm
{
    private $version;
    private $plugin_base;
    private $base_url;
    private $base_dir;
    private $user_caps = 'manage_categories';
    private $page_hook_s;
    private $page_hook_f;
    private $db;
    private $pluginNameComment;

    private $defaultFollowText;
    private $defaultShareText;

    // ajax response msgs
    private $urlErrorResponse;
    private $sidebarErrorResponse;
    private $queueErrorResponse;
    private $genericErrorResponse;

    private static $instance;
    public static function GetInstance($version, $base)
    {
        if (!isset(self::$instance)) {
            self::$instance = new self($version, $base);
        }
        return self::$instance;
    }

    public function __construct($version, $base)
    {
        $this->base_url = plugin_dir_url(__FILE__);
        $this->base_dir = plugin_dir_path(__FILE__);
        $this->version = $version;
        $this->plugin_base = plugin_basename($base);
        require_once $this->base_dir . '/inc/data/db.php';
        $this->db = spbsm_db::GetInstance();
        register_activation_hook($base, array($this, 'initialize'));
        if (get_option('spbsm_db_version') != $this->db->db_version) {
            $this->initialize();
        }
        add_action('init', array($this, 'localizeStrings'));
        add_action('admin_menu', array($this, 'add_menu_items'));
        add_action('admin_enqueue_scripts', array($this, 'backend_enqueue'));
        add_action('wp_enqueue_scripts', array($this, 'frontend_enqueue'));
        add_filter('plugin_row_meta', array($this, 'plugin_row_meta'), 10, 2);
        add_action('wp_ajax_spbsmAjax', array($this, 'spbsmAjax'));
        add_shortcode('spbsm-share-buttons', array($this, 'frontend_share'));
        add_shortcode('spbsm-follow-buttons', array($this, 'frontend_follow'));
        $this->setPositionSettingFilters();
        $this->pluginNameComment = '<!-- Superb Social Share and Follow Buttons -->';
        add_action('admin_init', array($this, 'spbsm_spbThemesNotification'), 9);

        if (is_admin() && !class_exists('SuperbThemes\AddonsRecommender\NoticeController')) {
            require_once $this->base_dir . '/recommender/recommender.php';
            \SuperbThemes\AddonsRecommender\NoticeController::init();
        }
    }
    public function spbsm_spbThemesNotification()
    {
        $notifications = include($this->base_dir . '/admin_notification/Autoload.php');
        $options = array("delay" => "+2 days");
        $notifications->Add("spbsm_admin_notification", "Unlock All Features with Social Media Buttons Premium", "
		
            Take advantage of the up to <span style='font-weight:bold;'>40% discount</span> and unlock all features for Superb Social Media Buttons Premium. 
            The discount is only available for a limited time.
    
            <div>
            <a style='margin-bottom:15px;' class='button button-large button-secondary' target='_blank' href='https://superbthemes.com/plugins/social-media-share-and-follow-buttons/'>Read more</a> <a style='margin-bottom:15px;' class='button button-large button-primary' target='_blank' href='https://superbthemes.com/plugins/social-media-share-and-follow-buttons/'>Buy now</a>
            </div>
    
            ", "info", $options);
        $notifications->Boot();
    }

    public function localizeStrings()
    {
        $this->localizeFront();
        $this->localizeBack();
    }

    private function localizeFront()
    {
        $this->defaultFollowText = esc_html__("Follow us on Social Media", 'superb-social-share-and-follow-buttons');
        $this->defaultShareText = esc_html__("Share on Social Media", 'superb-social-share-and-follow-buttons');
    }

    private function localizeBack()
    {
        $this->queueErrorResponse =  esc_html__("Couldn't save settings. Order data invalid.", 'superb-social-share-and-follow-buttons');
        $this->urlErrorResponse =  esc_html__("Couldn't save settings. Profile link should be https.", 'superb-social-share-and-follow-buttons');
        $this->sidebarErrorResponse =  esc_html__("Couldn't save settings. Sidebar setting invalid.", 'superb-social-share-and-follow-buttons');
        $this->genericErrorResponse = esc_html__("Couldn't save settings. Data invalid.", 'superb-social-share-and-follow-buttons');
    }

    public function plugin_row_meta($row_meta, $file)
    {
        if ($this->plugin_base == $file) {
            $row_meta[] = '<a href="' . admin_url('admin.php?page=spbsm') . '" aria-label="Options">Options</a>';
        }
        return $row_meta;
    }

    public function add_menu_items()
    {
        $user_caps = apply_filters('spbsm_user_capabilities', $this->user_caps);
        $has_menu = menu_page_url('spbhlpr', false);
        if ($has_menu) {
            $this->page_hook_s = add_submenu_page('spbhlpr', 'Share Buttons', 'Share Buttons', $user_caps, 'spbsm', array($this, 'backend_share'), 1);
            $this->page_hook_f = add_submenu_page('spbhlpr', 'Follow Buttons', 'Follow Buttons', $user_caps, 'spbsm-follow', array($this, 'backend_follow'), 1);
        } else {
            add_menu_page('Superb Social Share and Follow Buttons', 'Superb Social Media Buttons', $user_caps, 'spbsm', array($this, 'backend_share'), $this->base_url . "assets/img/icon.png");
            $this->page_hook_s = add_submenu_page('spbsm', 'Share Buttons', 'Share Buttons', $user_caps, 'spbsm');
            $this->page_hook_f = add_submenu_page('spbsm', 'Follow Buttons', 'Follow Buttons', $user_caps, 'spbsm-follow', array($this, 'backend_follow'));
        }
    }

    public function backend_enqueue($hook)
    {
        if ($hook == $this->page_hook_s || $hook == $this->page_hook_f) {
            wp_enqueue_style('spbsm-backend', $this->base_url . '/assets/css/backend.css', false, $this->version, 'all');
            $this->frontend_enqueue();
            wp_enqueue_script('spbsm-tablednd', $this->base_url . '/js/jquery.tablednd.js', array('jquery'), $this->version, true);
            wp_enqueue_script('spbsm-script', $this->base_url . '/js/backend.js', array('jquery', 'wp-color-picker'), $this->version, true);
            wp_enqueue_style('wp-color-picker');
            wp_localize_script('spbsm-script', 'msgs', array(
                'alreadySaved'  => esc_html__("Current settings already saved..", 'superb-social-share-and-follow-buttons'),
                'error' => esc_html__("Couldn't save settings..", 'superb-social-share-and-follow-buttons'),
                'fieldErrorMultiple' => esc_html__("fields are not valid profile links..", 'superb-social-share-and-follow-buttons'),
                'fieldErrorSingle' => esc_html__("field is not a valid profile link..", 'superb-social-share-and-follow-buttons'),
                'fieldErrorExpected' => esc_html__(" Expected https://(site).com/(profile) or similar.", 'superb-social-share-and-follow-buttons'),
            ));
        }
    }

    public function frontend_enqueue()
    {
        wp_enqueue_style('spbsm-stylesheet', $this->base_url . '/assets/css/frontend.css', false, $this->version, 'all');
        wp_enqueue_style('spbsm-lato-font', $this->base_url . '/assets/lato/styles.css', false, $this->version, 'all');
    }

    private function review_banner()
    {
?>
        <div class="review-banner">
            <p><span>&#128075;</span> Hi there! We sincerely hope you're enjoying our superb social media buttons plugin. Please consider <a href="https://wordpress.org/support/plugin/superb-social-share-and-follow-buttons/reviews/" target="_blank">reviewing it here</a>. It means the world to us!</p>
        </div>
<?php
    }

    public function backend_share()
    {
        $this->review_banner();
        include_once $this->base_dir . "/inc/backend_share.php";
    }

    public function backend_follow()
    {
        $this->review_banner();
        include_once $this->base_dir . "/inc/backend_follow.php";
    }

    public function frontend_share()
    {
        $this->localizeFront();
        $buttons = $this->db->getShareButtons();
        if ($buttons) {
            $permlink = get_permalink();
            $permlink = isset($permlink) && !empty($permlink) ? $permlink : get_home_url();
            $title = get_the_title();
            $title = isset($title) && !empty($title) ? $title : get_bloginfo("name");
            $logo = wp_get_attachment_image_src(get_theme_mod('custom_logo'));
            $logo = (isset($logo) && !empty($logo) && $logo !== false && is_array($logo)) ? $logo[0] : '';
            $thumb = get_the_post_thumbnail_url();
            $thumb = isset($thumb) && !empty($thumb) ? $thumb : $logo;
            $excerpt = apply_filters('the_excerpt', get_post_field('post_excerpt', get_the_ID()));
            $excerpt = isset($excerpt) && !empty($excerpt) ? $excerpt : get_bloginfo("description");
            ob_start();
            echo '<div class="spbsm-sharebuttons-output-wrapper">';
            echo wp_kses_post($this->pluginNameComment);
            echo '<div class="spbsm-output-textstring">' . esc_attr($this->defaultShareText) . '</div>';
            echo '<div class="spbsm-button-wrapper-flat">';
            foreach ($buttons as &$button) {
                $name = isset($button['alt-name']) ? $button['alt-name'] : $button['class'];
                $link = str_replace(
                    array('{url}', '{title}', '{img}', '{description}'),
                    array(esc_url($permlink), urlencode($title), $thumb, urlencode($excerpt)),
                    $button['share']
                );
                echo '<span class="spbsm-share-' . esc_attr($button['class']) . '"><a href="' . esc_url($link) . '" rel="nofollow" target="_blank">' . wp_kses($button['icon'], $this->getAllowedHTML());
                echo esc_attr($name);
                echo '</a></span>';
            }
            echo '</div></div>';
            return ob_get_clean();
        }
        return "";
    }

    private function getAllowedHTML()
    {
        return array(
            'svg' => array(
                'xmlns' => true,
                'width' => true,
                'height' => true,
                'viewbox' => true,
                'fill' => true,
                'xmlns:xlink' => true,
                'xml:space' => true,
                'role' => true,
                'aria-hidden' => true,
                'focusable' => true,
                'class' => true,
                'style' => true,
                'enable-background' => true,
                'image-rendering' => true,
                'preserveAspectRatio' => true,
                'shape-rendering' => true,
                'text-rendering' => true,
                'version' => true,
                'fill-rule' => true,
                'clip-rule' => true,
                'aria-label' => true,
                'role' => true,
                'xml:space' => true,
                'xmlns:svg' => true,
                'xmlns:xlink' => true,
                'x' => true,
                'y' => true
            ),
            'path' => array(
                'd' => true,
                'fill' => true,
                'transform' => true,
                'stroke' => true,
                'stroke-width' => true,
                'fill-rule' => true
            ),
            'g' => array(
                'fill' => true,
                'transform' => true,
                'stroke' => true,
                'stroke-width' => true
            ),
            'polygon' => array(
                'points' => true,
                'fill' => true,
                'transform' => true
            ),
            'circle' => array(
                'cx' => true,
                'cy' => true,
                'r' => true,
                'fill' => true,
                'transform' => true,
                'stroke' => true,
                'stroke-width' => true
            ),
            'rect' => array(
                'x' => true,
                'y' => true,
                'width' => true,
                'height' => true,
                'transform' => true,
                'fill' => true,
                'stroke' => true,
                'stroke-width' => true
            )
        );
    }

    public function frontend_follow()
    {
        $this->localizeFront();
        $buttons = $this->db->getFollowButtons();
        if ($buttons) {
            ob_start();
            echo '<div class="spbsm-followbuttons-output-wrapper">';
            echo wp_kses_post($this->pluginNameComment);
            echo '<div class="spbsm-output-textstring">' . esc_attr($this->defaultFollowText) . '</div>';
            echo '<div class="spbsm-button-wrapper-flat">';
            foreach ($buttons as &$button) {
                if ($button['class'] == 'email') {
                    continue;
                }
                $name = isset($button['alt-name']) ? $button['alt-name'] : $button['class'];
                echo '<span class="spbsm-follow-' . esc_attr($button['class']) . '"><a href="' . esc_url($button['follow_url']) . '" rel="nofollow" target="_blank">' . wp_kses($button['icon'], $this->getAllowedHTML());
                echo esc_html($name);
                echo '</a></span>';
            }
            echo '</div></div>';
            return ob_get_clean();
        }
        return "";
    }

    public function setPositionSettingFilters()
    {
        add_filter('the_content', array($this, 'addToContent'));
        add_filter('wp_footer', array($this, 'addSidebar'));
    }

    public function addToContent($content)
    {
        if (!is_single() && !is_page()) {
            return $content;
        }
        $prepend = "";
        $append = "";
        $scShare = null;
        $scFollow = null;
        $shareSettings = $this->db->get_positionSettings(1);
        $followSettings = $this->db->get_positionSettings(2);
        if (
            $shareSettings['posts_addAtStart'] == 1 || $shareSettings['posts_addAtEnd'] == 1 ||
            $shareSettings['pages_addAtStart'] == 1 || $shareSettings['pages_addAtEnd'] == 1
        ) {
            $scShare = do_shortcode('[spbsm-share-buttons]');
        }

        if (
            $followSettings['posts_addAtStart'] == 1 || $followSettings['posts_addAtEnd'] == 1 ||
            $followSettings['pages_addAtStart'] == 1 || $followSettings['pages_addAtEnd'] == 1
        ) {
            $scFollow = do_shortcode('[spbsm-follow-buttons]');
        }

        if (is_null($scFollow) && is_null($scShare)) {
            return $content;
        }

        if (is_single()) {
            if ($shareSettings['posts_addAtStart'] == 1) {
                $prepend .= $scShare;
            }
            if ($shareSettings['posts_addAtEnd'] == 1) {
                $append .= $scShare;
            }

            if ($followSettings['posts_addAtStart'] == 1) {
                $prepend .= $scFollow;
            }
            if ($followSettings['posts_addAtEnd'] == 1) {
                $append .= $scFollow;
            }
        } else {
            if ($shareSettings['pages_addAtStart'] == 1) {
                $prepend .= $scShare;
            }
            if ($shareSettings['pages_addAtEnd'] == 1) {
                $append .= $scShare;
            }

            if ($followSettings['pages_addAtStart'] == 1) {
                $prepend .= $scFollow;
            }
            if ($followSettings['pages_addAtEnd'] == 1) {
                $append .= $scFollow;
            }
        }

        return $prepend . $content . $append;
    }

    public function addSidebar()
    {
        $settings = $this->db->getSidebarSettings();
        if ($settings) {
            if ($settings[0]['sidebar'] == $settings[1]['sidebar']) {
                $hide = $settings[0]['hide'] == 1 || $settings[1]['hide'] == 1 ? ' spbsm-hideonmobile' : '';
                $class = 'spbsm-sidebar-wrapper';
                if ($settings[0]['sidebar'] == 1) {
                    $class .= '-leftcenter';
                }
                if ($settings[0]['sidebar'] == 2) {
                    $class .= '-rightcenter';
                }
                if ($settings[0]['sidebar'] == 3) {
                    $class .= '-bottomright';
                }
                if ($settings[0]['sidebar'] == 4) {
                    $class .= '-bottomleft';
                }
                echo '<div class="spbsm-sidebar-wrapper ' . esc_attr($class . $hide) . '">';
                echo do_shortcode('[spbsm-share-buttons]');
                echo do_shortcode('[spbsm-follow-buttons]');
                echo '</div>';
            } else {
                if ($settings[0]['sidebar'] > 0) {
                    $hide = $settings[0]['hide'] == 1 ? ' spbsm-hideonmobile' : '';
                    $class = 'spbsm-sidebar-wrapper';
                    if ($settings[0]['sidebar'] == 1) {
                        $class .= '-leftcenter';
                    }
                    if ($settings[0]['sidebar'] == 2) {
                        $class .= '-rightcenter';
                    }
                    if ($settings[0]['sidebar'] == 3) {
                        $class .= '-bottomright';
                    }
                    if ($settings[0]['sidebar'] == 4) {
                        $class .= '-bottomleft';
                    }
                    echo '<div class="spbsm-sidebar-wrapper ' . esc_attr($class . $hide) . '">';
                    echo do_shortcode('[spbsm-share-buttons]');
                    echo '</div>';
                }
                if ($settings[1]['sidebar'] > 0) {
                    $hide = $settings[1]['hide'] == 1 ? ' spbsm-hideonmobile' : '';
                    $class = 'spbsm-sidebar-wrapper';
                    if ($settings[1]['sidebar'] == 1) {
                        $class .= '-leftcenter';
                    }
                    if ($settings[1]['sidebar'] == 2) {
                        $class .= '-rightcenter';
                    }
                    if ($settings[1]['sidebar'] == 3) {
                        $class .= '-bottomright';
                    }
                    if ($settings[1]['sidebar'] == 4) {
                        $class .= '-bottomleft';
                    }
                    echo '<div class="spbsm-sidebar-wrapper ' . esc_attr($class . $hide) . '">';
                    echo do_shortcode('[spbsm-follow-buttons]');
                    echo '</div>';
                }
            }
        }
    }

    public function spbsmAjax()
    {
        if (!isset($_POST['cmd']) || !isset($_POST['nonce']) || !current_user_can($this->user_caps)) {
            wp_send_json(array('type' => 'error', 'msg' => $this->genericErrorResponse));
            exit();
        }
        $nonce = sanitize_text_field(wp_unslash($_POST['nonce']));
        if (!wp_verify_nonce($nonce, "spbsm_submit") || !check_ajax_referer("spbsm_submit", "nonce")) {
            wp_send_json(array('type' => 'error', 'msg' => $this->genericErrorResponse));
            exit();
        }
        $result = array();
        try {
            switch ($_POST['cmd']) {
                case 'save':
                    if (!isset($_POST['form']) || !isset($_POST['page'])) {
                        throw new Exception($this->genericErrorResponse);
                    }
                    $form = array();
                    $form_data = str_replace('&amp;', '&', wp_kses_post(wp_unslash($_POST['form'])));
                    parse_str($form_data, $form);
                    $sanitizedDto = $this->sanitize_form($form);
                    $page = sanitize_text_field(wp_unslash($_POST['page']));
                    if (!isset($sanitizedDto) || ($page != 'follow' && $page != 'share')) {
                        throw new Exception($this->genericErrorResponse);
                    }
                    $response = $page == 'share' ? $this->db->update_share($sanitizedDto) : $this->db->update_follow($sanitizedDto);
                    $result['type'] = $response[0];
                    $result['msg'] = $response[1];
                    break;

                default:
                    $result['type'] = "error";
                    $result['result'] = "invalid cmd";
                    break;
            }
        } catch (Exception $ex) {
            $result['type'] = 'error';
            $result['msg'] = $ex->getMessage();
        }
        wp_send_json($result);
    }


    ///sanitize user input
    private function sanitize_form($form)
    {
        try {
            //create Dto
            $sanitized = array();
            foreach ($form as $key => &$value) {
                $key = esc_sql(sanitize_text_field($key));
                switch ($key) {
                    case 'floatingSidebar':
                        $sanitized['floatingSidebar'] = $this->sanitize($form['floatingSidebar'], 'sidebar');
                        break;
                    case 'general':
                        foreach ($form['general'] as $key => $value) {
                            $sanitized['general'][esc_sql(sanitize_text_field($key))] = $this->sanitize($value, 'bit');
                        }
                        break;
                    case '_wpnonce':
                    case '_wp_http_referer':
                    case 'tabs':
                        //no need to include these fields in Dto.
                        break;
                    default:
                        if (isset($form[$key]['share'])) {
                            $sanitized[$key]['share'] = $this->sanitize($form[$key]['share'], 'bit');
                        }
                        if (isset($form[$key]['follow'])) {
                            $sanitized[$key]['follow'] = $this->sanitize($form[$key]['follow'], 'bit');
                        }
                        if (isset($form[$key]['follow_url'])) {
                            $sanitized[$key]['follow_url'] = $this->sanitize($form[$key]['follow_url'], 'url');
                        }
                        if (isset($form[$key]['share_queue'])) {
                            $sanitized[$key]['share_queue'] = $this->sanitize($form[$key]['share_queue'], 'queue');
                        }
                        if (isset($form[$key]['follow_queue'])) {
                            $sanitized[$key]['follow_queue'] = $this->sanitize($form[$key]['follow_queue'], 'queue');
                        }
                        break;
                }
            }
            return $sanitized;
        } catch (Exception $ex) {
            throw new Exception(esc_html($ex->getMessage()));
        }
    }

    private function sanitize($value, $type = '')
    {
        switch ($type) {
            case 'bit':
                return $value == 1 || $value == 'on' ? 1 : 0;
                break;

            case 'url':
                if (empty($value)) {
                    return null;
                }
                $url = esc_url_raw($value, ['https']);
                if (empty($url)) {
                    throw new Excepton(esc_html($this->urlErrorResponse));
                }
                return esc_sql($url);
                break;

            case 'sidebar':
                if (!is_int(intval($value))) {
                    throw new Exception(esc_html($this->sidebarErrorResponse));
                }
                return ($value < 0 || $value > 4) ? 0 : $value;
                break;

            case 'queue':
                $queue = intval($value);
                if ($queue < 0 || $queue > 200) {
                    throw new Exception(esc_html($this->queueErrorResponse));
                }
                return $queue;
                break;

            default:
                return esc_sql(sanitize_text_field($value));
                break;
        }
    }




    public function initialize()
    {
        $this->db->create_table();
    }
}
