<?php

/**
 * YouTube Feed Database
 *
 * @since 6.0
 */
namespace Smashballoon\Customizer;

class Feed_Saver
{
    /**
     * @var int
     *
     * @since 6.0
     */
    private $insert_id;
    /**
     * @var array
     *
     * @since 6.0
     */
    private $data;
    /**
     * @var array
     *
     * @since 6.0
     */
    private $sanitized_and_sorted_data;
    /**
     * @var array
     *
     * @since 6.0
     */
    private $feed_db_data;
    /**
     * @var string
     *
     * @since 6.0
     */
    private $feed_name;
    /**
     * @var bool
     *
     * @since 6.0
     */
    private $is_legacy;
    private $db;
    /**
     * @var ProxyProvider
     */
    private $proxy_provider;
    /**
     * SBY_Feed_Saver constructor.
     *
     * @since 2.0
     */
    public function __construct(\Smashballoon\Customizer\DB $db, \Smashballoon\Customizer\ProxyProvider $proxy_provider)
    {
        $this->db = $db;
        $this->proxy_provider = $proxy_provider;
    }
    public function set_feed_id($insert_id)
    {
        if ($insert_id === 'legacy') {
            $this->is_legacy = \true;
            $this->insert_id = 0;
        } else {
            $this->is_legacy = \false;
            $this->insert_id = $insert_id;
        }
    }
    /**
     * Feed insert ID if it exists
     *
     * @return bool|int
     *
     * @since 6.0
     */
    public function get_feed_id()
    {
        if ($this->is_legacy) {
            return 'legacy';
        }
        if (!empty($this->insert_id)) {
            return $this->insert_id;
        } else {
            return \false;
        }
    }
    /**
     * @param array $data
     *
     * @since 6.0
     */
    public function set_data($data)
    {
        $this->data = $data;
    }
    /**
     * @param string $feed_name
     *
     * @since 6.0
     */
    public function set_feed_name($feed_name)
    {
        $this->feed_name = $feed_name;
    }
    /**
     *
     * @return array
     *
     * @since 6.0
     */
    public function get_feed_db_data()
    {
        return $this->feed_db_data;
    }
    /**
     * Adds a new feed if there is no associated feed
     * found. Otherwise updates the exiting feed.
     *
     * @return false|int
     *
     * @since 6.0
     */
    public function update_or_insert()
    {
        $this->sanitize_and_sort_data();
        if ($this->exists_in_database()) {
            return $this->update();
        } else {
            return $this->insert();
        }
    }
    /**
     * Whether or not a feed exists with the
     * associated insert ID
     *
     * @return bool
     *
     * @since 6.0
     */
    public function exists_in_database()
    {
        if ($this->is_legacy) {
            return \true;
        }
        if ($this->insert_id === \false) {
            return \false;
        }
        $args = array('id' => $this->insert_id);
        $results = $this->db->feeds_query($args);
        return isset($results[0]);
    }
    /**
     * Inserts a new feed from sanitized and sorted data.
     * Some data is saved in the sbi_feeds table and some is
     * saved in the sbi_feed_settings table.
     *
     * @return false|int
     *
     * @since 6.0
     */
    public function insert()
    {
        if ($this->is_legacy) {
            return $this->update();
        }
        if (!isset($this->sanitized_and_sorted_data)) {
            return \false;
        }
        $settings_array = self::format_settings($this->sanitized_and_sorted_data['feed_settings']);
        $this->sanitized_and_sorted_data['feeds'][] = array('key' => 'settings', 'values' => array(json_encode($settings_array)));
        if (!empty($this->feed_name)) {
            $this->sanitized_and_sorted_data['feeds'][] = array('key' => 'feed_name', 'values' => array($this->feed_name));
        }
        $this->sanitized_and_sorted_data['feeds'][] = array('key' => 'status', 'values' => array('publish'));
        $insert_id = $this->db->feeds_insert($this->sanitized_and_sorted_data['feeds']);
        if ($insert_id) {
            $this->insert_id = $insert_id;
            return $insert_id;
        }
        return \false;
    }
    /**
     * Updates an existing feed and related settings from
     * sanitized and sorted data.
     *
     * @return false|int
     *
     * @since 6.0
     */
    public function update()
    {
        if (!isset($this->sanitized_and_sorted_data)) {
            return \false;
        }
        $args = array('id' => $this->insert_id);
        $settings_array = self::format_settings($this->sanitized_and_sorted_data['feed_settings']);
        if ($this->is_legacy) {
            $to_save_json = json_encode($settings_array);
            update_option('sbi_legacy_feed_settings', $to_save_json, \false);
            return \true;
        }
        $this->sanitized_and_sorted_data['feeds'][] = array('key' => 'settings', 'values' => array(json_encode($settings_array)));
        $this->sanitized_and_sorted_data['feeds'][] = array('key' => 'feed_name', 'values' => array(sanitize_text_field($this->feed_name)));
        $success = $this->db->feeds_update($this->sanitized_and_sorted_data['feeds'], $args);
        return $success;
    }
    /**
     * Converts settings that have been sanitized into an associative array
     * that can be saved as JSON in the database
     *
     * @param $raw_settings
     *
     * @return array
     *
     * @since 6.0
     */
    public static function format_settings($raw_settings)
    {
        $settings_array = array();
        foreach ($raw_settings as $single_setting) {
            if (count($single_setting['values']) > 1) {
                $settings_array[$single_setting['key']] = $single_setting['values'];
            } else {
                $settings_array[$single_setting['key']] = isset($single_setting['values'][0]) ? $single_setting['values'][0] : '';
            }
        }
        return $settings_array;
    }
    /**
     * Retrieves and organizes feed setting data for easy use in
     * the builder
     *
     * @return array|bool
     *
     * @since 6.0
     */
    public function get_feed_settings()
    {
        if ($this->is_legacy) {
            $feed_settings = $this->proxy_provider->get_settings_class();
            $feed_settings->set_feed_type_and_terms();
            $feed_settings->set_transient_name();
            $return = $feed_settings->get_legacy_feed_settings();
            $this->feed_db_data = array('id' => 'legacy', 'feed_name' => __('Legacy Feeds', 'feeds-for-youtube'), 'feed_title' => __('Legacy Feeds', 'feeds-for-youtube'), 'status' => 'publish', 'last_modified' => date('Y-m-d H:i:s'));
        } elseif (empty($this->insert_id)) {
            return \false;
        } else {
            $args = array('id' => $this->insert_id);
            $settings_db_data = $this->db->feeds_query($args);
            if (\false === $settings_db_data || sizeof($settings_db_data) === 0) {
                return \false;
            }
            $this->feed_db_data = array('id' => $settings_db_data[0]['id'], 'feed_name' => $settings_db_data[0]['feed_name'], 'feed_title' => $settings_db_data[0]['feed_title'], 'status' => $settings_db_data[0]['status'], 'last_modified' => $settings_db_data[0]['last_modified']);
            $return = json_decode($settings_db_data[0]['settings'], \true);
            $return['feed_name'] = $settings_db_data[0]['feed_name'];
        }
        $return = wp_parse_args($return, $this->proxy_provider->get_db_settings());
        if (empty($return['id'])) {
            return $return;
        }
        if (!is_array($return['id'])) {
            $return['id'] = explode(',', str_replace(' ', '', $return['id']));
        }
        if (!is_array($return['tagged'])) {
            $return['tagged'] = explode(',', str_replace(' ', '', $return['tagged']));
        }
        if (!is_array($return['hashtag'])) {
            $return['hashtag'] = explode(',', str_replace(' ', '', $return['hashtag']));
        }
        $args = array('id' => $return['id']);
        $source_query = $this->db->source_query($args);
        $return['sources'] = array();
        if (!empty($source_query)) {
            foreach ($source_query as $source) {
                $user_id = $source['account_id'];
                $return['sources'][$user_id] = self::get_processed_source_data($source);
            }
        } else {
            $found_sources = array();
            foreach ($return['id'] as $id_or_slug) {
                $maybe_source_from_connected = \Smashballoon\Customizer\Source::maybe_one_off_connected_account_update($id_or_slug);
                if ($maybe_source_from_connected) {
                    $found_sources[] = $maybe_source_from_connected;
                }
            }
            if (!empty($found_sources)) {
                foreach ($found_sources as $source) {
                    $user_id = $source['account_id'];
                    $return['sources'][$user_id] = self::get_processed_source_data($source);
                }
            } else {
                $source_query = $this->db->source_query($args);
                if (isset($source_query[0])) {
                    $source = $source_query[0];
                    $user_id = $source['account_id'];
                    $return['sources'][$user_id] = self::get_processed_source_data($source);
                }
            }
        }
        return $return;
    }
    public static function get_processed_source_data($source)
    {
        $encryption = new \SmashBalloon\YoutubeFeed\Vendor\SB_Instagram_Data_Encryption();
        $user_id = $source['account_id'];
        $info = !empty($source['info']) ? json_decode($encryption->decrypt($source['info']), \true) : array();
        $cdn_avatar_url = \SmashBalloon\YoutubeFeed\Vendor\SB_Instagram_Parse_Pro::get_avatar_url($info);
        $processed = array('record_id' => stripslashes($source['id']), 'user_id' => $user_id, 'type' => stripslashes($source['account_type']), 'privilege' => stripslashes($source['privilege']), 'access_token' => stripslashes($encryption->decrypt($source['access_token'])), 'username' => stripslashes($source['username']), 'name' => stripslashes($source['username']), 'info' => stripslashes($encryption->decrypt($source['info'])), 'error' => stripslashes($source['error']), 'expires' => stripslashes($source['expires']), 'profile_picture' => $cdn_avatar_url, 'local_avatar_url' => \SmashBalloon\YoutubeFeed\Vendor\SB_Instagram_Connected_Account::maybe_local_avatar($source['username'], $cdn_avatar_url));
        return $processed;
    }
    /**
     * Retrieves and organizes feed setting data for easy use in
     * the builder
     * It will NOT get the settings from the DB, but from the Customizer builder
     * To be used for updating feed preview on the fly
     *
     * @return array|bool
     *
     * @since 6.0
     */
    public function get_feed_settings_preview($settings_db_data)
    {
        if (\false === $settings_db_data || sizeof($settings_db_data) === 0) {
            return \false;
        }
        $return = $settings_db_data;
        $return = wp_parse_args($return, self::settings_defaults());
        if (empty($return['sources'])) {
            return $return;
        }
        $sources = array();
        foreach ($return['sources'] as $single_source) {
            array_push($sources, $single_source['account_id']);
        }
        $args = array('id' => $sources);
        $source_query = $this->db->source_query($args);
        $return['sources'] = array();
        if (!empty($source_query)) {
            foreach ($source_query as $source) {
                $user_id = $source['account_id'];
                $return['sources'][$user_id] = self::get_processed_source_data($source);
            }
        }
        return $return;
    }
    /**
     * Default settings, $return_array equalling false will return
     * the settings in the general way that the "SBI_Shortcode" class,
     * "sbi_get_processed_options" method does
     *
     * @param bool $return_array
     *
     * @return array
     *
     * @since 6.0
     */
    public static function settings_defaults($return_array = \true)
    {
        {
            $defaults = array(
                'connected_accounts' => array(),
                'type' => 'channel',
                'channel' => '',
                'num' => 9,
                'nummobile' => 9,
                'minnum' => 9,
                'widthresp' => \true,
                'class' => '',
                'height' => '',
                'heightunit' => '%',
                'disablemobile' => \false,
                'itemspacing' => 5,
                'itemspacingunit' => 'px',
                'background' => '',
                'headercolor' => '',
                'subscribecolor' => '',
                'subscribetextcolor' => '',
                'buttoncolor' => '',
                'buttonhovercolor' => '',
                'buttontextcolor' => '',
                'layout' => 'grid',
                'playvideo' => 'automatically',
                'sortby' => 'none',
                'imageres' => 'auto',
                'showheader' => \true,
                'showdescription' => \true,
                'showbutton' => \true,
                'headersize' => 'small',
                'headeroutside' => \false,
                'showsubscribe' => \true,
                'buttontext' => __('Load More...', 'feeds-for-youtube'),
                'subscribetext' => __('Subscribe', 'feeds-for-youtube'),
                'caching_type' => 'page',
                'cache_time' => 1,
                'cache_time_unit' => 'hours',
                'backup_cache_enabled' => \true,
                'resizeprocess' => 'background',
                'disable_resize' => \true,
                'storage_process' => 'background',
                'favor_local' => \false,
                'disable_js_image_loading' => \false,
                'ajax_post_load' => \false,
                'ajaxtheme' => \false,
                'enqueue_css_in_shortcode' => \false,
                'font_method' => 'svg',
                'customtemplates' => \false,
                'gallerycols' => 3,
                'gallerycolsmobile' => 2,
                'gridcols' => 3,
                'gridcolsmobile' => 2,
                'playerratio' => '9:16',
                'eagerload' => \false,
                'custom_css' => '',
                'custom_js' => '',
                'gdpr' => 'auto',
                'disablecdn' => \false,
                'allowcookies' => \false,
                // pro only
                'usecustomsearch' => \false,
                'headerchannel' => '',
                'customsearch' => '',
                'showpast' => \true,
                'showlikes' => \true,
                'carouselcols' => 3,
                'carouselcolsmobile' => 2,
                'carouselarrows' => \true,
                'carouselpag' => \true,
                'carouselautoplay' => \false,
                'infoposition' => 'below',
                'include' => array('title', 'icon', 'user', 'views', 'date', 'countdown'),
                'hoverinclude' => array('description', 'stats'),
                'descriptionlength' => 150,
                'userelative' => \true,
                'dateformat' => '0',
                'customdate' => '',
                'showsubscribers' => \true,
                'subscriberstext' => __('subscribers', 'feeds-for-youtube'),
                'viewstext' => __('views', 'feeds-for-youtube'),
                'agotext' => __('ago', 'feeds-for-youtube'),
                'beforedatetext' => __('Streaming live', 'feeds-for-youtube'),
                'beforestreamtimetext' => __('Streaming live in', 'feeds-for-youtube'),
                'minutetext' => __('minute', 'feeds-for-youtube'),
                'minutestext' => __('minutes', 'feeds-for-youtube'),
                'hourstext' => __('hours', 'feeds-for-youtube'),
                'thousandstext' => __('K', 'feeds-for-youtube'),
                'millionstext' => __('M', 'feeds-for-youtube'),
                'watchnowtext' => __('Watch Now', 'feeds-for-youtube'),
                'cta' => 'related',
                'colorpalette' => 'inherit',
                'linktext' => __('Learn More', 'feeds-for-youtube'),
                'linkurl' => '',
                'linkopentype' => 'same',
                'linkcolor' => '',
                'linktextcolor' => '',
                'custombgcolor1' => '',
                'customtextcolor1' => '',
                'customtextcolor2' => '',
                'customlinkcolor1' => '',
                'custombuttoncolor1' => '',
                'custombuttoncolor2' => '',
            );
            $defaults = self::filter_defaults($defaults);
            // some settings are comma separated and not arrays when the feed is created
            if ($return_array) {
                $settings_with_multiples = array('sources');
                foreach ($settings_with_multiples as $multiple_key) {
                    if (isset($defaults[$multiple_key])) {
                        $defaults[$multiple_key] = explode(',', $defaults[$multiple_key]);
                    }
                }
            }
            return $defaults;
        }
    }
    /**
     * Provides backwards compatibility for extensions
     *
     * @param array $defaults
     *
     * @return array
     *
     * @since 6.0
     */
    public static function filter_defaults($defaults)
    {
        return $defaults;
    }
    /**
     * Used for taking raw post data related to settings
     * an sanitizing it and sorting it to easily use in
     * the database tables
     *
     * @since 6.0
     */
    private function sanitize_and_sort_data()
    {
        $data = $this->data;
        $sanitized_and_sorted = array('feeds' => array(), 'feed_settings' => array());
        foreach ($data as $key => $value) {
            $data_type = $this->get_data_type($key);
            $sanitized_values = array();
            if (is_array($value)) {
                foreach ($value as $item) {
                    $type = $this->is_boolean($item) ? 'boolean' : $data_type['sanitization'];
                    $sanitized_values[] = $this->sanitize($type, $item);
                }
            } else {
                $type = $this->is_boolean($value) ? 'boolean' : $data_type['sanitization'];
                $sanitized_values[] = $this->sanitize($type, $value);
            }
            $single_sanitized = array('key' => $key, 'values' => $sanitized_values);
            $sanitized_and_sorted[$data_type['table']][] = $single_sanitized;
        }
        $this->sanitized_and_sorted_data = $sanitized_and_sorted;
    }
    /**
     * Determines what table and sanitization should be used
     * when handling feed setting data.
     *
     * TODO: Add settings that need something other than sanitize_text_field
     *
     * @param string $key
     *
     * @return array
     *
     * @since 2.0
     */
    private function get_data_type($key)
    {
        switch ($key) {
            case 'feed_name':
            case 'status':
            case 'feed_title':
                $return = array('table' => 'feeds', 'sanitization' => 'sanitize_text_field');
                break;
            case 'author':
                $return = array('table' => 'feeds', 'sanitization' => 'int');
                break;
            default:
                $return = array('table' => 'feed_settings', 'sanitization' => 'sanitize_text_field');
                break;
        }
        return $return;
    }
    /**
     * Check if boolean
     * for a value
     *
     * @param string $type
     * @param int|string $value
     *
     * @return int|string
     *
     * @since 2.0
     */
    private function is_boolean($value)
    {
        return $value === 'true' || $value === 'false' || is_bool($value);
    }
    private function cast_boolean($value)
    {
        return $value === 'true' || $value === \true || $value === 'on';
    }
    /**
     * Uses the appropriate sanitization function and returns the result
     * for a value
     *
     * @param string $type
     * @param int|string $value
     *
     * @return int|string
     *
     * @since 2.0
     */
    private function sanitize($type, $value)
    {
        switch ($type) {
            case 'int':
                $return = (int) $value;
                break;
            case 'boolean':
                $return = $this->cast_boolean($value);
                break;
            default:
                $return = sanitize_text_field($value);
                break;
        }
        return $return;
    }
    /**
     * Returns an associate array of all existing sources along with their data
     *
     * @param int $page
     *
     * @return array
     *
     * @since 6.0
     */
    public function get_source_list($page = 1)
    {
        $args['page'] = $page;
        return $this->db->source_query($args);
    }
}
