<?php

namespace RemoveUnusedMedia\Core;

require_once 'rum_util.php';
require_once 'rum_db.php';
use Throwable;
use function preg_match;
use RemoveUnusedMedia\Util as Util;
use RemoveUnusedMedia\DB as DB;
const URLREGEX = '/(https?:\\/\\/|\\/)(?:\\([-A-Z\\xCC\\x880-9+&@#\\/%=~_|$?!:,.]*\\)|[-A-Z\\xCC\\x880-9+&@#\\/%=~_|$?!:,.])*(?:\\([-A-Z\\xCC\\x880-9+&@#\\/%=~_|$?!:,.]*\\)|[A-Z\\xCC\\x880-9+&@#\\/%=~_|$])/im';
final class How {
    private static $single = [
        'divi_builder'      => 'content',
        'muffin_gallery'    => 'content',
        'wpbakery_0'        => 'content',
        'wpbakery_1'        => 'content',
        'wpbakery_2'        => 'content',
        'wpbakery_3'        => 'content',
        'wpbakery_4'        => 'content',
        'thrive-apprentice' => 'Thrive Apprentice Plugin',
    ];

    private static $two = [
        'featured_image' => [
            'download'          => 'featured_image',
            'product'           => 'product_image',
            'product_variation' => 'product_variation',
        ],
        'content'        => [
            'product'            => 'product_description',
            'revision'           => 'revision',
            'tablepress_table'   => 'tablepress_table',
            'tcb_symbol'         => 'content',
            'wpcf7_contact_form' => 'cf7',
        ],
    ];

    private static $three = [
        'options' => [
            '*' => [
                '/aioseo_options/'                  => '',
                '/CookieLawInfo.*/'                 => 'gdpr_cookie',
                '/rank-math-options-titles/'        => 'rankmath_social',
                '/tve_leads.*/'                     => 'thrive_leads',
                '/widget_media_image/'              => 'image_widget',
                '/wp-short-pixel-bulk-last-status/' => '',
                '/wpseo_social/'                    => 'yoast_social',
                '/wpseo_titles/'                    => 'yoast_company',
            ],
        ],
        'meta'    => [
            'download'           => [
                '/product_item_thumbnail->\\d+/' => 'product_thumbnail',
            ],
            '3d-flip-book'       => [
                '/.+/' => 'flipbook3d_pdf',
            ],
            'kadslider'          => [
                '/.+/' => 'kadence',
            ],
            'thrive_template'    => [
                '/.+/' => 'thrive_template',
            ],
            'tvo_testimonials'   => [
                '/.+/' => 'thrive_testimonial',
            ],
            'wpcf7_contact_form' => [
                '/_form->\\d+/' => 'cf7_contact',
            ],
            '*'                  => [
                '/_elementor_data->\\d+/'                => 'content',
                '/_fl_builder_data->\\d+/'               => 'content',
                '/_fl_builder_draft->\\d+/'              => '',
                '/_yoast_wpseo_opengraph-image->\\d/'    => 'yoast_fb',
                '/_yoast_wpseo_twitter-image->\\d/'      => 'yoast_twitter',
                '/mfn-page-items(-seo)?->\\d+/'          => 'content',
                '/rank_math_facebook_image->\\d+/'       => 'rankmath_fb',
                '/rank_math_twitter_image->\\d+/'        => 'rankmath_twitter',
                '/_themify_builder_settings_json->\\d+/' => 'themify',
                '/tve_content.*/'                        => 'content',
                '/tve_custom_css->\\d+/'                 => 'content',
                '/tve_custom_css_blank_v2/'              => 'content',
                '/tve_save_post.*/'                      => 'content',
                '/tve_updated_post.*/'                   => 'content',
                '/wp_schema_pro_.*/'                     => 'wp_schema_pro',
            ],
        ],
    ];

    public static function replace( $how ) {
        if ( is_array( $how ) ) {
            if ( 2 == count( $how ) ) {
                if ( isset( self::$two[$how[0]][$how[1]] ) ) {
                    return self::$two[$how[0]][$how[1]];
                }
                return $how;
            }
            if ( 3 == count( $how ) ) {
                if ( isset( self::$three[$how[0]] ) ) {
                    foreach ( self::$three[$how[0]][$how[1]] as $r => $v ) {
                        if ( preg_match( $r, $how[2] ) ) {
                            return $v;
                        }
                    }
                    foreach ( self::$three[$how[0]]['*'] as $r => $v ) {
                        if ( preg_match( $r, $how[2] ) ) {
                            return $v;
                        }
                    }
                }
                return $how;
            }
        }
        if ( isset( self::$single[$how] ) ) {
            return self::$single[$how];
        }
        return $how;
    }

}

function match_url(  $data  ) : array {
    $data = stripslashes( $data );
    if ( !$data ) {
        return [];
    }
    preg_match_all( URLREGEX, $data, $matches );
    $site_url = get_site_url();
    $site_url_alt = $site_url;
    #workaround for http links
    $site_url_alt2 = $site_url;
    #workaround for // links
    if ( strpos( $site_url, 'https' ) === 0 ) {
        $site_url_alt = 'http' . substr( $site_url, 5 );
        $site_url_alt2 = substr( $site_url, 6 );
    } elseif ( strpos( $site_url, 'http' ) === 0 ) {
        $site_url_alt = 'https' . substr( $site_url, 4 );
        $site_url_alt2 = substr( $site_url, 5 );
    }
    $possible_matches = [];
    foreach ( $matches[0] as $match ) {
        if ( strpos( $match, $site_url ) === 0 ) {
            $match = substr( $match, strlen( $site_url ) );
        } elseif ( strpos( $match, $site_url_alt ) === 0 ) {
            $match = substr( $match, strlen( $site_url_alt ) );
        } elseif ( strpos( $match, $site_url_alt2 ) === 0 ) {
            $match = substr( $match, strlen( $site_url_alt2 ) );
        }
        $url = preg_replace( '/-\\d+[Xx]\\d+\\./', '.', $match );
        $possible_matches[] = $url;
        $possible_matches[] = substr_replace(
            $url,
            '-scaled',
            strrpos( $url, '.' ),
            0
        );
    }
    $possible_matches = array_unique( $possible_matches );
    $images = [];
    foreach ( array_chunk( $possible_matches, 5 ) as $p ) {
        $q = "'" . join( "','", $p ) . "'";
        foreach ( DB\get_col( DB\RESULT, 'id', "url IN ({$q})" ) as $id ) {
            if ( !in_array( $id, $images ) ) {
                $images[] = $id;
            }
        }
    }
    return $images;
}

function regex_post(
    $data,
    $regex,
    $how,
    $post_id
) {
    if ( $data ) {
        if ( preg_match_all( $regex, $data, $matches ) ) {
            found_post( $matches[1], $how, $post_id );
        }
    }
}

function search_post(  $data, $how, $post_id  ) {
    found_post( match_url( $data ), $how, $post_id );
}

function search(
    $data,
    $how,
    $where,
    $where_url = null
) {
    found(
        match_url( $data ),
        $how,
        $where,
        $where_url
    );
}

function found_post(  $ids, $how, $post_id  ) {
    if ( $ids ) {
        foreach ( $ids as $id ) {
            if ( !is_numeric( $post_id ) ) {
                $post_id = intval( $post_id );
            }
            found( $id, $how, $post_id );
        }
    }
}

function found(
    $id,
    $how,
    $where,
    $where_url = null
) {
    if ( !$id ) {
        return;
    }
    if ( is_array( $id ) ) {
        foreach ( $id as $i ) {
            found(
                $i,
                $how,
                $where,
                $where_url
            );
        }
        return;
    }
    if ( strpos( $id, ',' ) ) {
        found(
            explode( ',', $id ),
            $how,
            $where,
            $where_url
        );
        return;
    }
    if ( $where_url ) {
        $where = "<a href='{$where_url}' target='_blank'>{$where}</a>";
    }
    $how = How::replace( $how );
    if ( !$how ) {
        return;
    }
    $data = DB\get_row( DB\RESULT, ['used_where', 'used_how'], [
        'id' => $id,
    ] );
    if ( isset( $data['error'] ) ) {
        return;
    }
    if ( !$data['used_where'] ) {
        $data['used_where'] = [];
        $data['used_how'] = [];
    } else {
        $data['used_where'] = unserialize( $data['used_where'] );
        $data['used_how'] = unserialize( $data['used_how'] );
    }
    $index = array_search( $where, $data['used_where'] );
    $update = false;
    if ( $index === false ) {
        $data['used_where'][] = $where;
        $data['used_how'][] = [$how];
        $update = true;
    } elseif ( !in_array( $how, $data['used_how'][$index] ) ) {
        $data['used_how'][$index][] = $how;
        $update = true;
    }
    if ( $update ) {
        $data['used_where'] = serialize( $data['used_where'] );
        $data['used_how'] = serialize( $data['used_how'] );
        DB\update( DB\RESULT, $data, [
            'id' => $id,
        ] );
    }
}

function find_media_in_content() {
    $how = 'content';
    $type = get_post_type();
    if ( 'post' != $type && 'page' != $type ) {
        $how = [$how, $type];
    }
    try {
        $filtered = apply_filters( 'the_content', get_the_content() );
        search_post( $filtered, $how, get_the_ID() );
        search_post( get_the_content(), $how, get_the_ID() );
    } catch ( Throwable $e ) {
        $error_types = get_option( 'rum_error_types', [] );
        if ( !in_array( $type, $error_types ) ) {
            $error_types[] = $type;
            update_option( 'rum_error_types', $error_types );
        }
    }
}

function find_media_in_thumbnail() {
    if ( has_post_thumbnail() ) {
        $how = 'featured_image';
        $type = get_post_type();
        if ( 'post' != $type && 'page' != $type ) {
            $how = [$how, $type];
        }
        found_post( [get_post_thumbnail_id()], $how, get_the_ID() );
    }
}

function find_media_meta() {
    $how = ['meta', ''];
    $type = get_post_type();
    if ( 'post' != $type && 'page' != $type ) {
        $how[1] = $type;
    }
    foreach ( get_post_meta( get_the_ID() ) as $key => $value ) {
        if ( 'wpil_' === substr( $key, 0, 5 ) ) {
            continue;
        }
        if ( !is_array( $value ) ) {
            search_post( $value, array_merge( $how, [$key] ), get_the_ID() );
            continue;
        }
        foreach ( $value as $key2 => $value2 ) {
            search_post( $value2, array_merge( $how, [$key . '->' . $key2] ), get_the_ID() );
        }
    }
}

function find_media_favicon() {
    $id = attachment_url_to_postid( get_site_icon_url() );
    found( $id, 'favicon', __( 'Everywhere', 'remove-unused-media' ) );
}

function find_media_in_options() {
    $rum_keys = [
        'rum_cache',
        'rum_data',
        'remove-unused-media',
        'rum_cached'
    ];
    foreach ( wp_load_alloptions() as $key => $value ) {
        if ( in_array( $key, $rum_keys ) ) {
            continue;
        }
        search( $value, ['options', '', $key], __( 'Options', 'remove-unused-media' ) );
    }
}

function find_media_in_theme() {
    //style.css
    search( file_get_contents( get_stylesheet_uri() ), __( "Theme" ), "style.css" );
    //template style.css
    search( file_get_contents( get_template_directory_uri() . '/style.css' ), __( "Template" ), "style.css" );
}

function find_media(  $from  ) {
    Util\debug_logging( "find_media {$from}" );
    $num_posts = 0;
    update_status( __( 'Analyzing posts: ', 'remove-unused-media' ) );
    foreach ( Util\get_posts( false, $from ) as $post_id ) {
        find_media_in_content();
        find_media_in_thumbnail();
        find_media_meta();
        $num_posts++;
        update_status( 'posts', $from + $num_posts );
    }
}

function analyze() {
    wp_cache_delete( 'rum_analysis_running', 'options' );
    $status = get_option( 'rum_analysis_running' );
    if ( $status['media'][0] < $status['media'][1] ) {
        list_of_images( $status['media'][0] );
        $status = get_option( 'rum_analysis_running' );
        if ( $status['media'][0] < $status['media'][1] ) {
            return 0;
        }
    }
    if ( $status['posts'][0] < $status['posts'][1] ) {
        find_media( $status['posts'][0] );
        $status2 = get_option( 'rum_analysis_running' );
        if ( $status['posts'][0] < $status2['posts'][0] && $status2['posts'][0] < $status2['posts'][1] ) {
            return 0;
        }
    }
    find_media_favicon();
    update_status( __( 'Analyzing settings', 'remove-unused-media' ) );
    find_media_in_options();
    update_status( __( 'Analyzing Theme', 'remove-unused-media' ) );
    find_media_in_theme();
    update_status( __( 'Analyzing Plugins', 'remove-unused-media' ) );
    update_status( __( 'Compiling results', 'remove-unused-media' ) );
    analytics();
    return true;
}

function startup_analysis() {
    update_option( 'rum_analysis_running', __( 'Starting Analysis', 'remove-unused-media' ) );
    update_option( 'rum_analysis_running', [
        'status' => __( 'Starting Analysis', 'remove-unused-media' ),
        'media'  => [0, Util\num_media()],
        'posts'  => [0, Util\num_posts()],
    ] );
    update_option( 'rum_error_types', [] );
    DB\drop( 'rum_result' );
    DB\create_result_table();
}

function list_of_images(  $from  ) {
    Util\debug_logging( 'list_of_images ' . $from );
    update_status( __( 'Compiling list of media', 'remove-unused-media' ) );
    $site_url_len = strlen( get_site_url() );
    $count = 0;
    foreach ( Util\get_media( $from ) as $id ) {
        $url = wp_get_attachment_url( $id );
        $url_warning = !filter_var( $url, FILTER_VALIDATE_URL );
        DB\insert( DB\RESULT, [
            'id'          => $id,
            'url'         => substr( $url, $site_url_len ),
            'url_warning' => $url_warning,
        ] );
        $count++;
        update_status( 'media', $from + $count );
    }
}

function analytics() {
    if ( 'yes' != get_option( 'rum_analytics', 'no' ) ) {
        return;
    }
    $plugins = get_plugins();
    $remove_keys = [
        'Author',
        'Description',
        'RequiresWP',
        'RequiresPHP',
        'Network',
        'AuthorName',
        'TextDomain',
        'Title',
        'DomainPath',
        'AuthorURI'
    ];
    foreach ( $plugins as $p => $plug ) {
        $plugins[$p] = array_diff_key( $plug, array_flip( $remove_keys ) );
    }
    $rum = array_values( get_plugins( '/' . explode( '/', plugin_basename( __FILE__ ) )[0] ) )[0];
    $num = Util\num_posts();
    $data = [
        'time'         => time(),
        'url'          => get_site_url(),
        'rum_version'  => $rum['Version'],
        'used'         => Util\num_used(),
        'ignored'      => Util\num_ignored(),
        'unused'       => Util\num_unused(),
        'trashed'      => get_option( 'rum_trashed', [] ),
        'deleted'      => get_option( 'rum_deleted', [] ),
        'num_analysis' => get_option( 'rum_analysis_counter', 0 ) + 1,
        'posts'        => $num,
        'PHP'          => PHP_VERSION,
        'WP'           => get_bloginfo( 'version' ),
        'plugins'      => $plugins,
    ];
    wp_remote_post( 'https://remove-unused-media.com/analytics', [
        'body' => [
            'rum_analytics' => json_encode( $data ),
        ],
    ] );
}

function update_status(  $new_status, $value = null  ) {
    $status = get_option( 'rum_analysis_running' );
    if ( is_null( $value ) ) {
        $status['status'] = $new_status;
    } else {
        $status[$new_status][0] = $value;
    }
    update_option( 'rum_analysis_running', $status );
    wp_cache_delete( 'rum_analysis_running', 'options' );
}
