<?php

namespace ILJ\Helper;

use  ILJ\Core\Options as CoreOptions ;
use  ILJ\Posttypes\CustomLinks ;
use  ILJ\Helper\Blacklist ;
use  ILJ\Backend\Editor ;
use  ILJ\Core\App ;
use  ILJ\Database\Linkindex ;
use  ILJ\Database\LinkindexIndividualTemp ;
use  ILJ\Database\LinkindexTemp ;
/**
 * Toolset for linkindex assets
 *
 * Methods for handling linkindex data
 *
 * @package ILJ\Helper
 * @since   1.1.0
 */
class IndexAsset
{
    const  ILJ_FILTER_INDEX_ASSET = 'ilj_index_asset_title' ;
    const  ILJ_FILTER_MUFFIN_BUILDER_FIELD = 'ilj_index_mb_field' ;
    const  ILJ_FULL_BUILD = 'full' ;
    const  ILJ_INDIVIDUAL_BUILD = 'individual' ;
    /**
     * Returns all meta data to a specific asset from index
     *
     * @since  1.1.0
     * @param  int    $id   The id of the asset
     * @param  string $type The type of the asset (post, term or custom)
     * @return object
     */
    public static function getMeta( $id, $type )
    {
        if ( 'post' != $type || 'post_meta' == $type ) {
            return null;
        }
        
        if ( 'post' == $type || 'post_meta' == $type ) {
            $post = get_post( $id );
            if ( !$post ) {
                return null;
            }
            $asset_title = $post->post_title;
            $asset_url = get_the_permalink( $post->ID );
            $asset_url_edit = get_edit_post_link( $post->ID );
        }
        
        if ( !isset( $asset_title ) || !isset( $asset_url ) ) {
            return null;
        }
        $meta_data = (object) [
            'title'    => $asset_title,
            'url'      => $asset_url,
            'url_edit' => $asset_url_edit,
        ];
        /**
         * Filters the index asset
         *
         * @since 1.6.0
         *
         * @param object $meta_data The index asset
         * @param string $type The asset type
         * @param int $id The asset id
         */
        $meta_data = apply_filters(
            self::ILJ_FILTER_INDEX_ASSET,
            $meta_data,
            $type,
            $id
        );
        return $meta_data;
    }
    
    /**
     * Returns all relevant posts for linking
     *
     * @since  1.2.0
     * @return array
     */
    public static function getPosts()
    {
        $whitelist = CoreOptions::getOption( \ILJ\Core\Options\Whitelist::getKey() );
        if ( !is_array( $whitelist ) || !count( $whitelist ) ) {
            return [];
        }
        $args = [
            'posts_per_page'   => -1,
            'post__not_in'     => Blacklist::getBlacklistedList( "post" ),
            'post_type'        => $whitelist,
            'post_status'      => [ 'publish' ],
            'suppress_filters' => true,
            'orderby'          => 'ID',
            'order'            => 'DESC',
            'lang'             => 'all',
        ];
        $query = new \WP_Query( $args );
        $post_count = $query->post_count;
        return $query->posts;
    }
    
    /**
     * Returns relevant posts for linking
     *
     * @since  2.0.3
     * @return array
     */
    public static function getPostsBatched( $building_batch_size, $offset )
    {
        $whitelist = CoreOptions::getOption( \ILJ\Core\Options\Whitelist::getKey() );
        if ( !is_array( $whitelist ) || !count( $whitelist ) ) {
            return [];
        }
        $args = [
            'posts_per_page'   => $building_batch_size,
            'post__not_in'     => Blacklist::getBlacklistedList( "post" ),
            'post_type'        => $whitelist,
            'post_status'      => [ 'publish' ],
            'suppress_filters' => true,
            'offset'           => $offset,
            'orderby'          => 'ID',
            'order'            => 'DESC',
            'lang'             => 'all',
        ];
        $query = new \WP_Query( $args );
        $post_count = $query->post_count;
        return $query->posts;
    }
    
    /**
     * Gets the concrete type of an asset
     *
     * @since 1.2.5
     * @param string $id   ID of asset
     * @param string $type Generic type of asset
     *
     * @return string
     */
    public static function getDetailedType( $id, $type )
    {
        if ( $type == 'post' ) {
            $detailed_type = get_post_type( $id );
        }
        return $detailed_type;
    }
    
    /**
     * Get Incoming Links Count
     *
     * @param  int $id - Post/term ID to count incoming links
     * @param  string $type 
     * @param  string $scope 
     * @param  int $exclude_id - Exclude this Post/term ID to count incoming links
     * @param  string $exclude_type
     * @return int
     */
    public static function getIncomingLinksCount(
        $id,
        $type,
        $scope,
        $exclude_id = null,
        $exclude_type = null
    )
    {
        global  $wpdb ;
        
        if ( $scope == IndexAsset::ILJ_FULL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexTemp::ILJ_DATABASE_TABLE_LINKINDEX_TEMP;
        } elseif ( $scope == IndexAsset::ILJ_INDIVIDUAL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexIndividualTemp::ILJ_DATABASE_TABLE_LINKINDEX_INDIVIDUAL_TEMP;
        }
        
        $query = "";
        
        if ( $exclude_id != null ) {
            $ilj_linkindex_table = $wpdb->prefix . Linkindex::ILJ_DATABASE_TABLE_LINKINDEX;
            $query = " AND (link_from != '" . $exclude_id . "' AND type_from != '" . $exclude_type . "')";
            $incoming_links_old = $wpdb->get_var( "SELECT count(link_to) FROM {$ilj_linkindex_table} WHERE (link_to = '" . $id . "' AND type_to = '" . $type . "') " . $query );
            $ilj_linkindex_table_new = $wpdb->prefix . LinkindexIndividualTemp::ILJ_DATABASE_TABLE_LINKINDEX_INDIVIDUAL_TEMP;
            $incoming_links_new = $wpdb->get_var( "SELECT count(link_to) FROM {$ilj_linkindex_table_new} WHERE (link_from != 0 AND type_from != '') AND ( (link_to = '" . $id . "' AND type_to = '" . $type . "') )" );
            $incoming_links = (int) $incoming_links_old + (int) $incoming_links_new;
            return (int) $incoming_links;
        }
        
        $incoming_links = $wpdb->get_var( "SELECT count(link_to) FROM {$ilj_linkindex_table} WHERE (link_from != 0 AND type_from != '') AND ( (link_to = '" . $id . "' AND type_to = '" . $type . "') " . $query . " )" );
        return (int) $incoming_links;
    }
    
    /**
     * Get Outgoing Links Count
     *
     * @param  int    $id   Post/Tax ID
     * @param  string $type Type
     * @param  string $scope
     * @return int
     */
    public static function getOutgoingLinksCount( $id, $type, $scope )
    {
        global  $wpdb ;
        $sql = "";
        
        if ( $scope == IndexAsset::ILJ_FULL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexTemp::ILJ_DATABASE_TABLE_LINKINDEX_TEMP;
        } elseif ( $scope == IndexAsset::ILJ_INDIVIDUAL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexIndividualTemp::ILJ_DATABASE_TABLE_LINKINDEX_INDIVIDUAL_TEMP;
        }
        
        $additional_query = "";
        $outgoing = $wpdb->get_var( "SELECT count(link_from) FROM {$ilj_linkindex_table} WHERE (link_to != 0 AND type_to != '') AND (link_from = '" . $id . "' AND ( type_from = '" . $type . "' " . $additional_query . " ))" );
        return (int) $outgoing;
    }
    
    /**
     * getLinkedUrlsCount
     *
     * @param  int $link_to_id
     * @param  int $id
     * @param  string $type
     * @param  string $scope
     * @return int
     */
    public static function getLinkedUrlsCount(
        $link_to_id,
        $id,
        $type,
        $scope
    )
    {
        global  $wpdb ;
        
        if ( $scope == IndexAsset::ILJ_FULL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexTemp::ILJ_DATABASE_TABLE_LINKINDEX_TEMP;
        } elseif ( $scope == IndexAsset::ILJ_INDIVIDUAL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexIndividualTemp::ILJ_DATABASE_TABLE_LINKINDEX_INDIVIDUAL_TEMP;
        }
        
        $additional_query = "";
        $linked_urls = $wpdb->get_var( "SELECT count(link_to) FROM {$ilj_linkindex_table} WHERE (link_from = '" . $id . "' AND link_to = '" . $link_to_id . "' AND (type_from = '" . $type . "' " . $additional_query . " ))" );
        $linked_url_value[$link_to_id] = (int) $linked_urls;
        return $linked_urls;
    }
    
    /**
     * Get Linked Anchors
     *
     * @param  int    $id   Post/Tax ID
     * @param  string $type Type
     * @param  string $scope
     * @return mixed
     */
    public static function getLinkedAnchors( $id, $type, $scope )
    {
        global  $wpdb ;
        
        if ( $scope == IndexAsset::ILJ_FULL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexTemp::ILJ_DATABASE_TABLE_LINKINDEX_TEMP;
        } elseif ( $scope == IndexAsset::ILJ_INDIVIDUAL_BUILD ) {
            $ilj_linkindex_table = $wpdb->prefix . LinkindexIndividualTemp::ILJ_DATABASE_TABLE_LINKINDEX_INDIVIDUAL_TEMP;
        }
        
        $additional_query = "";
        $linked_anchors = $wpdb->get_results( "SELECT anchor FROM {$ilj_linkindex_table} WHERE (link_to != 0 AND type_to != '' AND anchor != '') AND (link_from = '" . $id . "' AND ( type_from = '" . $type . "' " . $additional_query . " ))", ARRAY_A );
        $anchors = [];
        foreach ( $linked_anchors as $key => $value ) {
            $anchors[] = $value["anchor"];
        }
        return $anchors;
    }
    
    /**
     * Checks if the phrase is included in the blacklist of keywords
     *
     * @param  int    $link_from post/term ID
     * @param  string $phrase    string to check for 
     * @param  string $type      could be term/post
     * @return bool
     */
    public static function checkIfBlacklistedKeyword( $link_from, $phrase, $type )
    {
        if ( $type == 'post' || $type == 'post_meta' ) {
            $keyword_blacklist = get_post_meta( $link_from, Editor::ILJ_META_KEY_BLACKLISTDEFINITION, true );
        }
        if ( $type == 'term' || $type == 'term_meta' ) {
            $keyword_blacklist = get_term_meta( $link_from, Editor::ILJ_META_KEY_BLACKLISTDEFINITION, true );
        }
        
        if ( !empty($keyword_blacklist) || $keyword_blacklist != false ) {
            $keyword_blacklist = array_slice( $keyword_blacklist, 0, 2 );
            foreach ( $keyword_blacklist as $keyword ) {
                if ( strtolower( $phrase ) == strtolower( $keyword ) ) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * This function removes post/term metas that starts with _ or ilj_
     *
     * @param  array $allmeta           Array of all meta fields
     * @return array $custom_fields     Array of custom metas
     */
    public static function filter_custom_fields( $allmeta )
    {
        $custom_fields = array();
        if ( $allmeta ) {
            foreach ( $allmeta as $key => $value ) {
                if ( substr( $value["meta_key"], 0, 1 ) != "_" && substr( $value["meta_key"], 0, 4 ) != "ilj_" ) {
                    $custom_fields[$value["meta_key"]] = $value["meta_value"];
                }
            }
        }
        $custom_fields = array_map( 'maybe_unserialize', $custom_fields );
        return $custom_fields;
    }
    
    /**
     * getMetaData
     *
     * @param  int $id
     * @param  string $type
     * @param  mixed $key
     * @param  bool $single
     * @return mixed
     */
    public static function getMetaData(
        $id,
        $type,
        $key = null,
        $single = true
    )
    {
        global  $wpdb ;
        if ( !is_numeric( $id ) ) {
            return;
        }
        $type_key = "post_id";
        $table = $wpdb->postmeta;
        
        if ( $type == "term" ) {
            $type_key = "term_id";
            $table = $wpdb->termmeta;
        }
        
        $query = " AND meta_key = '{$key}' ";
        if ( $key == null ) {
            $query = "";
        }
        $data = "meta_value";
        if ( !$single ) {
            $data = "*";
        }
        $select = "SELECT " . $data . " FROM " . $table;
        $query = $wpdb->prepare( $select . " WHERE {$type_key} = %d " . $query, $id );
        
        if ( $single ) {
            $meta_data = $wpdb->get_var( $query );
        } elseif ( !$single ) {
            $meta_data = $wpdb->get_results( $query, ARRAY_A );
        }
        
        return $meta_data;
    }

}