<?php

/**
 * LinkCentral User Agent Parser Utility
 *
 * This class provides shared functionality for parsing user agent strings
 * to extract browser, device, and operating system information.
 *
 * Supports both:
 * - Full user agent strings (e.g., "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...")
 * - Parsed format (e.g., "Chrome|macOS|desktop") from imported data (e.g. ThirstyAffiliates)
 *
 * Uses substring matching (strpos) for compatibility with both formats.
 */
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class LinkCentral_User_Agent_Parser {

    /**
     * Extract browser name from user agent string.
     *
     * @param string $user_agent The user agent string to parse.
     * @param string $default_value The default value to return for empty user agents.
     * @return string The browser name.
     */
    public static function get_browser($user_agent, $default_value = 'Other/Unknown') {
        if (empty($user_agent)) {
            return $default_value;
        }

        $ua_lower = strtolower($user_agent);

        // Check for browsers in order of specificity
        if (strpos($user_agent, 'Edg/') !== false
            || strpos($user_agent, 'Edge/') !== false
            || strpos($user_agent, 'EdgiOS') !== false
            || strpos($user_agent, 'EdgA/') !== false) {
            return 'Edge';
        } elseif (strpos($user_agent, 'OPR/') !== false
            || strpos($ua_lower, 'opera mini') !== false
            || strpos($ua_lower, 'opera mobi') !== false
            || strpos($user_agent, 'Opera/') !== false
            || strpos($user_agent, 'Opera|') === 0) {
            return 'Opera';
        } elseif (strpos($user_agent, 'CriOS') !== false) {
            return 'Chrome';
        } elseif (strpos($user_agent, 'FxiOS') !== false) {
            return 'Firefox';
        } elseif (strpos($user_agent, 'Chrome') !== false && strpos($user_agent, 'Edg/') === false) {
            return 'Chrome';
        } elseif (strpos($user_agent, 'Firefox') !== false) {
            return 'Firefox';
        } elseif (strpos($user_agent, 'Safari') !== false
            && strpos($user_agent, 'Chrome') === false
            && strpos($user_agent, 'CriOS') === false
            && strpos($user_agent, 'FxiOS') === false) {
            return 'Safari';
        } elseif (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Trident/') !== false) {
            return 'Internet Explorer';
        } else {
            return 'Other/Unknown';
        }
    }

    /**
     * Extract device type from user agent string.
     *
     * @param string $user_agent The user agent string to parse.
     * @param string $default_value The default value to return for empty user agents.
     * @return string The device type (Mobile, Tablet, Desktop).
     */
    public static function get_device($user_agent, $default_value = 'Other/Unknown') {
        if (empty($user_agent)) {
            return $default_value;
        }

        return self::parse_device_type($user_agent);
    }

    /**
     * Extract operating system from user agent string.
     *
     * @param string $user_agent The user agent string to parse.
     * @param string $default_value The default value to return for empty user agents.
     * @return string The operating system name.
     */
    public static function get_operating_system($user_agent, $default_value = 'Other/Unknown') {
        if (empty($user_agent)) {
            return $default_value;
        }

        return self::parse_operating_system($user_agent);
    }

    /**
     * Parse device type from user agent string (internal method).
     *
     * @param string $user_agent The user agent string to parse.
     * @return string Mobile, Tablet, or Desktop.
     */
    private static function parse_device_type($user_agent) {
        $user_agent = strtolower($user_agent);

        // Tablets first (more specific)
        if (strpos($user_agent, 'tablet') !== false
            || strpos($user_agent, 'ipad') !== false
            || strpos($user_agent, 'kindle') !== false
            || (strpos($user_agent, 'android') !== false && strpos($user_agent, 'mobile') === false)) {
            return 'Tablet';
        }

        if (strpos($user_agent, 'mobile') !== false
            || strpos($user_agent, 'android') !== false
            || strpos($user_agent, 'iphone') !== false
            || strpos($user_agent, 'ipod') !== false
            || strpos($user_agent, 'blackberry') !== false
            || strpos($user_agent, 'windows phone') !== false
            || strpos($user_agent, 'silk') !== false
            || strpos($user_agent, 'opera mini') !== false) {
            return 'Mobile';
        }

        return 'Desktop';
    }

    /**
     * Parse operating system from user agent string (internal method).
     *
     * @param string $user_agent The user agent string to parse.
     * @return string The operating system name.
     */
    private static function parse_operating_system($user_agent) {
        // Check for operating systems in order of specificity
        if (strpos($user_agent, 'Windows NT 10.0') !== false) {
            return 'Windows 10/11';
        } elseif (strpos($user_agent, 'Windows NT 6.3') !== false) {
            return 'Windows 8.1';
        } elseif (strpos($user_agent, 'Windows NT 6.2') !== false) {
            return 'Windows 8';
        } elseif (strpos($user_agent, 'Windows NT 6.1') !== false) {
            return 'Windows 7';
        } elseif (strpos($user_agent, 'Windows NT') !== false) {
            return 'Windows';
        } elseif (strpos($user_agent, 'iPhone') !== false
            || strpos($user_agent, 'iPad') !== false
            || strpos($user_agent, 'iPod') !== false
            || strpos($user_agent, 'iPhone OS') !== false
            || strpos($user_agent, 'CPU iPhone OS') !== false
            || strpos($user_agent, 'iOS') !== false) {
            return 'iOS';
        } elseif (strpos($user_agent, 'Mac OS X') !== false || strpos($user_agent, 'macOS') !== false) {
            return 'macOS';
        } elseif (strpos($user_agent, 'Android') !== false) {
            return 'Android';
        } elseif (strpos($user_agent, 'Linux') !== false) {
            return 'Linux';
        } elseif (strpos($user_agent, 'CrOS') !== false) {
            return 'Chrome OS';
        } else {
            return 'Other/Unknown';
        }
    }

    /**
     * WordPress dashicon for a device type.
     *
     * @param string $device_type Mobile, Tablet, or Desktop.
     * @return string Dashicon class name.
     */
    private static function device_type_icon($device_type) {
        switch ($device_type) {
            case 'Mobile':
                return 'dashicons-smartphone';
            case 'Tablet':
                return 'dashicons-tablet';
            default:
                return 'dashicons-desktop';
        }
    }

    /**
     * Get device type, icon, and operating system from user agent string.
     * This method returns an array with device information including WordPress dashicons.
     *
     * @param string $user_agent The user agent string to parse.
     * @param string $default_value The default value to return for empty user agents.
     * @return array Array containing 'type', 'icon', and 'os' keys.
     */
    public static function get_device_and_os($user_agent, $default_value = 'Other/Unknown') {
        if (empty($user_agent)) {
            return array(
                'type' => $default_value,
                'icon' => 'dashicons-desktop',
                'os' => $default_value
            );
        }

        $device_type = self::parse_device_type($user_agent);

        return array(
            'type' => $device_type,
            'icon' => self::device_type_icon($device_type),
            'os'   => self::parse_operating_system($user_agent),
        );
    }

    /**
     * Get comprehensive user agent information including browser, device, and OS.
     *
     * @param string $user_agent The user agent string to parse.
     * @param string $default_value The default value to return for empty user agents.
     * @return array Array containing browser, device, and OS information.
     */
    public static function get_user_agent_info($user_agent, $default_value = 'Other/Unknown') {
        $device_and_os = self::get_device_and_os($user_agent, $default_value);

        return array(
            'browser' => self::get_browser($user_agent, $default_value),
            'device' => $device_and_os['type'],
            'device_icon' => $device_and_os['icon'],
            'os' => $device_and_os['os']
        );
    }

    /**
     * Whether a raw user agent string matches a parsed drill-down dimension value.
     *
     * @param string $user_agent Raw user agent from stats.
     * @param string $type       browser, device, or operating_system.
     * @param string $value      Parsed label from the chart.
     * @return bool
     */
    public static function matches_dimension( $user_agent, $type, $value ) {
        switch ( $type ) {
            case 'browser':
                return self::get_browser( $user_agent ) === $value;
            case 'device':
                return self::get_device( $user_agent ) === $value;
            case 'operating_system':
                return self::get_operating_system( $user_agent ) === $value;
            default:
                return false;
        }
    }
}
