<?php

/**
 * Parses module file and retrieves module metadata
 *
 * @param  string $module_file Path to module file
 *
 * @return array
 */
function wpuf_pro_get_module_data( $module_file ) {
    $default_headers = array(
        'name'        => 'Plugin Name',
        'description' => 'Description',
        'plugin_uri'  => 'Plugin URI',
        'thumbnail'   => 'Thumbnail Name',
        'class'       => 'Integration Class',
        'author'      => 'Author',
        'author_uri'  => 'Author URI',
        'version'     => 'Version',
    );

    $module_data = get_file_data( $module_file, $default_headers, 'wpuf_pro_modules' );

    return $module_data;
}

/**
 * Gets all the available modules
 *
 * @return array
 */
function wpuf_pro_get_modules() {
    $module_root  = WPUF_PRO_MODULES;
    $modules_dir  = @opendir( $module_root);
    $modules      = array();
    $module_files = array();

    if ( $modules_dir ) {

        while ( ( $file = readdir( $modules_dir ) ) !== false ) {

            if ( substr( $file, 0, 1 ) == '.' ) {
                continue;
            }

            if ( is_dir( $module_root . '/' . $file ) ) {
                $plugins_subdir = @opendir( $module_root . '/' . $file );

                if ( $plugins_subdir ) {

                    while ( ( $subfile = readdir( $plugins_subdir ) ) !== false ) {
                        if ( substr( $subfile, 0, 1 ) == '.' ) {
                            continue;
                        }

                        if ( substr($subfile, -4) == '.php' ) {
                            $module_files[] = "$file/$subfile";
                        }
                    }

                    closedir( $plugins_subdir );
                }
            }
        }

        closedir( $modules_dir );
    }

    if ( $module_files ) {

        foreach ( $module_files as $module_file ) {

            if ( ! is_readable( "$module_root/$module_file" ) ) {
                continue;
            }

            $module_data = wpuf_pro_get_module_data( "$module_root/$module_file" );

            if ( empty ( $module_data['name'] ) ) {
                continue;
            }

            $file_base = wp_normalize_path( $module_file );


            $modules[ $file_base ] = $module_data;
        }
    }

    return $modules;
}

/**
 * Get a single module data
 *
 * @param  string $module
 *
 * @return WP_Error|Array
 */
function wpuf_pro_get_module( $module ) {
    $module_root  = WPUF_PRO_MODULES;

    $module_data = wpuf_pro_get_module_data( "$module_root/$module" );

    if ( empty ( $module_data['name'] ) ) {
        return new WP_Error( 'not-valid-plugin', __( 'This is not a valid plugin', 'wpuf-pro' ) );
    }

    return $module_data;
}

/**
 * Get the meta key to store the active module list
 *
 * @return string
 */
function wpuf_pro_active_module_key() {
    return 'wpuf_pro_active_modules';
}

/**
 * Get active modules
 *
 * @return array
 */
function wpuf_pro_get_active_modules() {
    return get_option( wpuf_pro_active_module_key(), array() );
}

/**
 * Read the plan -> module-dir map (pack.json at the plugin root).
 *
 * @since 4.2.14
 *
 * @return array
 */
function wpuf_pro_plan_manifest() {
    static $manifest = null;

    if ( null !== $manifest ) {
        return $manifest;
    }

    $file     = WPUF_PRO_ROOT . '/pack.json';
    $manifest = array();

    if ( is_readable( $file ) ) {
        $decoded = json_decode( file_get_contents( $file ), true );

        if ( is_array( $decoded ) ) {
            $manifest = $decoded;
        }
    }

    $manifest = apply_filters( 'wpuf_pro_plan_modules', $manifest );

    return $manifest;
}

/**
 * Map a normalised Appsero license title to a pack.json plan key.
 *
 * @since 4.2.14
 *
 * @param string $title
 * @param array  $plans
 *
 * @return string
 */
function wpuf_pro_match_plan( $title, $plans ) {
    if ( '' === $title || empty( $plans ) ) {
        return '';
    }

    // AppSumo is its own variation (module set == business).
    if ( false !== strpos( $title, 'appsumo' ) ) {
        return in_array( 'appsumo', $plans, true ) ? 'appsumo' : 'business';
    }

    $is_lifetime = ( false !== strpos( $title, 'ltd' ) ) || ( false !== strpos( $title, 'lifetime' ) );
    $tier        = '';

    if ( false !== strpos( $title, 'business' ) ) {
        $tier = 'business';
    } elseif ( false !== strpos( $title, 'professional' ) ) {
        $tier = 'professional';
    } elseif ( false !== strpos( $title, 'personal' ) ) {
        $tier = 'personal';
    }

    if ( '' === $tier ) {
        return '';
    }

    if ( $is_lifetime && in_array( 'lifetime-' . $tier, $plans, true ) ) {
        return 'lifetime-' . $tier;
    }

    return in_array( $tier, $plans, true ) ? $tier : '';
}

/**
 * Resolve the customer's plan key from the Appsero license title.
 *
 * WPUF stores the plan signal in the `wpuf_license` option `title`
 * (e.g. "wpuf-pro-ltd-appsumo"); `source_id` is null, so the title is the
 * only reliable tier source. Returns '' when there is no valid license, which
 * leaves module loading unrestricted (existing behaviour preserved).
 *
 * @since 4.2.14
 *
 * @return string
 */
function wpuf_pro_current_plan() {
    static $plan = null;

    if ( null !== $plan ) {
        return $plan;
    }

    $license = get_option( 'wpuf_license', array() );
    $license = is_array( $license ) ? $license : array();

    $valid = ! empty( $license['key'] ) && isset( $license['status'] ) && 'activate' === $license['status'];

    if ( ! $valid ) {
        $plan = '';

        return $plan;
    }

    $title = isset( $license['title'] ) ? strtolower( (string) $license['title'] ) : '';
    $plans = array_keys( wpuf_pro_plan_manifest() );

    $plan = apply_filters( 'wpuf_pro_current_plan', wpuf_pro_match_plan( $title, $plans ), $license );

    return $plan;
}

/**
 * Allowed module directory slugs for the current plan.
 *
 * @since 4.2.14
 *
 * @return array
 */
function wpuf_pro_plan_allowed_dirs() {
    $plan     = wpuf_pro_current_plan();
    $manifest = wpuf_pro_plan_manifest();

    if ( '' === $plan || empty( $manifest[ $plan ] ) ) {
        return array();
    }

    return (array) $manifest[ $plan ];
}

/**
 * Directory slug from an active-module entry.
 *
 * "social-login/social-login.php" => "social-login"
 *
 * @since 4.2.14
 *
 * @param string $module_file
 *
 * @return string
 */
function wpuf_pro_module_dir( $module_file ) {
    $module_file = str_replace( '\\', '/', (string) $module_file );
    $parts       = explode( '/', trim( $module_file, '/' ) );

    return isset( $parts[0] ) ? $parts[0] : '';
}

/**
 * Whether the current plan may load/activate a module.
 *
 * No valid license/plan (dev sites or the free-fallback path) is NOT enforced,
 * so existing behaviour is preserved. Modules absent from pack.json are ungated.
 *
 * @since 4.2.14
 *
 * @param string $module_file "dir/file.php"
 *
 * @return bool
 */
function wpuf_pro_is_module_allowed( $module_file ) {
    $plan = wpuf_pro_current_plan();

    if ( '' === $plan ) {
        return true;
    }

    $manifest = wpuf_pro_plan_manifest();
    $gated    = array();

    foreach ( $manifest as $dirs ) {
        $gated = array_merge( $gated, (array) $dirs );
    }

    $dir = wpuf_pro_module_dir( $module_file );

    if ( ! in_array( $dir, $gated, true ) ) {
        return true;
    }

    return in_array( $dir, wpuf_pro_plan_allowed_dirs(), true );
}

/**
 * Lowest base plan tier that unlocks a module ('personal' | 'professional' | 'business').
 *
 * Lifetime/appsumo variants mirror the base tiers, so only the base ladder is
 * considered. Returns '' when the module is not gated by any tier.
 *
 * @since 4.2.14
 *
 * @param string $module_file "dir/file.php"
 *
 * @return string
 */
function wpuf_pro_module_required_plan( $module_file ) {
    $dir      = wpuf_pro_module_dir( $module_file );
    $manifest = wpuf_pro_plan_manifest();
    $ladder   = apply_filters( 'wpuf_pro_plan_ladder', array( 'personal', 'professional', 'business' ) );

    foreach ( $ladder as $plan ) {
        if ( ! empty( $manifest[ $plan ] ) && in_array( $dir, $manifest[ $plan ], true ) ) {
            return $plan;
        }
    }

    return '';
}

/**
 * Check if a module is active
 *
 * @param  string $module basename
 *
 * @return boolean
 */
function wpuf_pro_is_module_active( $module ) {
    return in_array( $module, wpuf_pro_get_active_modules() );
}

/**
 * Check if a module is inactive
 *
 * @param  string $module basename
 *
 * @return boolean
 */
function wpuf_pro_is_module_inactive( $module ) {
    return ! wpuf_pro_is_module_active( $module );
}

/**
 * Activate a module
 *
 * @param  string $module basename of the module file
 *
 * @return WP_Error|null WP_Error on invalid file or null on success.
 */
function wpuf_pro_activate_module( $module ) {
    $current = wpuf_pro_get_active_modules();

    $module_root = WPUF_PRO_MODULES;
    $module_data = wpuf_pro_get_module_data( "$module_root/$module" );

    if ( empty ( $module_data['name'] ) ) {
        return new WP_Error( 'invalid-module', __( 'The module is invalid', 'wpuf-pro' ) );
    }

    // activate if enactive
    if ( wpuf_pro_is_module_inactive( $module ) ) {
        $current[] = $module;
        sort($current);

        // deactivate the addon if exists
        $module_class = wpuf_module_class_map( $module );

        if ( $module_class && class_exists( $module_class ) ) {
            $reflector = new ReflectionClass( $module_class );
            $addon_path = plugin_basename( $reflector->getFileName() );

            deactivate_plugins( $addon_path );

            return new WP_Error( 'plugin-exists', __( 'Deactivated the plugin, please try again.', 'wpuf-pro' ) );
        }

        $file_path = plugin_basename( "$module_root/$module" );

        if ( file_exists( "$module_root/$module" ) ) {
            require_once "$module_root/$module";
            do_action( "wpuf_activate_{$file_path}", $module );
        }

        update_option( wpuf_pro_active_module_key(), $current );
    }

    return null;
}

/**
 * Deactivate a module
 *
 * @param  string $module basename of the module file
 *
 * @return boolean
 */
function wpuf_pro_deactivate_module( $module ) {
    $current = wpuf_pro_get_active_modules();

    if ( wpuf_pro_is_module_active( $module ) ) {

        $key = array_search( $module, $current );

        if ( false !== $key ) {
            unset( $current[ $key ] );
            sort($current);
        }

        $module_root = WPUF_PRO_MODULES;
        $file_path = plugin_basename( "$module_root/$module" );

        if ( file_exists( "$module_root/$module" ) ) {
            require_once "$module_root/$module";
            do_action( "wpuf_deactivate_{$file_path}", $module );
        }

        update_option( wpuf_pro_active_module_key(), $current );

        return true;
    }

    return false;
}

/**
 * wpuf register activation hook description]
 *
 * @param string $file     full file path
 * @param array|string $function callback function
 *
 * @return void
 */
function wpuf_register_activation_hook( $file, $function ) {
    if ( file_exists( $file ) ) {
        require_once $file;
        $base_name = plugin_basename( $file );
        add_action( "wpuf_activate_{$base_name}", $function );
    }
}

/**
 * wpuf register deactivation hook description]
 *
 * @param string $file     full file path
 * @param array|string $function callback function
 *
 * @return void
 */
function wpuf_register_deactivation_hook( $file, $function ) {
    if ( file_exists( $file ) ) {
        require_once $file;
        $base_name = plugin_basename( $file );
        add_action( "wpuf_deactivate_{$base_name}", $function );
    }
}

function wpuf_module_class_map( $module='' ) {
    $modules = apply_filters( 'wpuf_module_list', array(
        'bp-profile/wpuf-bp.php'                    => 'WPUF_BP_Profile',
        'comments/comments.php'                     => 'WPUF_Comments',
        'mailchimp/wpuf-mailchimp.php'              => 'WPUF_Mailchimp',
        'mailpoet/wpuf-mailpoet.php'                => 'WPUF_Mailpoet',
        'pmpro/wpuf-pmpro.php'                      => 'WPUF_Pm_Pro',
        'qr-code-addons/wpuf-qr-code.php'           => 'WPUF_QR_Code',
        'sms-notification/wpuf-sms.php'             => 'WPUF_Admin_sms',
        'stripe/wpuf-stripe.php'                    => 'WPUF_Stripe',
        'user-analytics/wpuf-user-analytics.php'    => 'WPUF_User_Analytics',
        'user-directory/userlisting.php'            => 'WPUF_User_Listing',
        'seo/wpuf-seo.php'                          => 'WPUF_SEO_Settings',
    ) );

    if ( array_key_exists( $module, $modules) ) {
        return $modules[ $module ];
     }

    return false;
}

add_filter( 'wp-user-frontend_tracker_data', 'wpuf_add_modules_data' );

/**
 * Send Modules data with tracking
 *
 * @since 2.8.1
 *
 * @param array $data
 *
 * @return array
 */
function wpuf_add_modules_data( $data ) {
    $modules = wpuf_pro_get_modules();

    foreach ( $modules as $key=>$module ) {
        if ( wpuf_pro_is_module_active( $key ) ) {
            $data['modules']['active'][] = $module['name'];
        } else {
            $data['modules']['inactive'][] = $module['name'];
        }
    }
    return $data;
}

