<?php

/**
 * This module is used when showing a list of compatible operating systems.
 * This module allows you to display the list, sorted based on the designated priorities, and uses JavaScript
 * to check if the user is using one of the supported operating systems. If the user is, it will feature that operating
 * system above the list.
 */
class Os
{
    private $operatingSystems;

    /**
     * Os constructor.
     * @param array $operatingSystems
     */
    public function __construct($operatingSystems) {
        $this->operatingSystems = $operatingSystems;
    }

    /**
     * Parses the OS string, looks up the matching patterns to be use for user-agent checking via JS, and sorts the list.
     *
     * @return array
     */
    public function getOperatingSystemsList(){
        $osList = $this->operatingSystems;
        $osMatchingPatterns = $this->getOperatingSystemMatchingPatterns();

        foreach($osMatchingPatterns as $key => $os){
            if(!in_array($os['name'], $osList)){
                unset($osMatchingPatterns[$key]);
            } else {
                unset($osList[array_search($os['name'], $osList)]);
            }
        }

        $osMatchingPatterns = array_values($osMatchingPatterns);
        usort($osMatchingPatterns, function($a, $b){
            if ($a['sortOrder'] == $b['sortOrder']) {
                return 0;
            }
            return ($a['sortOrder'] > $b['sortOrder']) ? -1 : 1;
        });

        foreach($osList as $os){
            $osMatchingPatterns[] = array('name' => $os, 'searchString' => '');
        }

        return $osMatchingPatterns;
    }

    /**
     * @return array
     */
    public function getOperatingSystemMatchingPatterns(){
        $path = __DIR__ . '/operatingSystemMatchingPatterns.json';
        $data = file_get_contents($path);

        return json_decode($data, true);
    }
}

/*
 * In this example we're saying:
 * This software works with these operating systems
 */
$os = new Os(array(
    "Win XP",
    "Windows Vista",
    "Win 2008 Server",
    "Windows 7",
    "Windows 8",
    "Linux",
    "Mac OS",
));

$osList = $os->getOperatingSystemsList();
?>

<?php
/*****************************************************************************/

/*
 * Here starts the "view" section. Normally you'd use a templating engine for this; here we use plain PHP so that
 * this example doesn't require any additional libraries
 */
if(count($osList) > 1): ?>
<div class='OS--Featured'>
	<p>Compatible with <span class='FirstOs'><?php echo $osList[0]['name'] ?></span>
        and <u><?php echo count($osList) - 1 ?> other</u> systems.</p>
</div>
<div class='OS--Others'>
	<ul class='OS__List' data-module='detailPageOsDetection'>
	<?php foreach($osList as $os): ?>
		<li data-matchingPattern='<?php echo $os['searchString'] ?>' itemprop="operatingSystem" content="<?php echo $os['name'] ?>">
            <?php echo $os['name'] ?>
        </li>
	<?php endforeach ?>
	</ul>
</div>
<?php else: ?>
<div class='OS--Featured'>
	<p>Compatible with <span class='FirstOs'>{$osList[0]['name']}</span></p>
</div>
<?php endif;

/*****************************************************************************/
?>

<script>
    /*
     * Here starts the JavaScript section. Again, normally you'd separate this into a separate file
     */
    osDetection = {
        userAgent: "",
        matchedOs: "",

        checkOs: function(item) {
            var self = this,
                matchingPattern = $(item).attr('data-matchingPattern');

            if(matchingPattern == '') {
                return;
            }

            var re = new RegExp(matchingPattern);

            if(re.test(self.userAgent)){
                self.matchedOs = $(item).html();
            }
        },

        init: function(el) {
            var self = this;

            self.userAgent = navigator.userAgent;

            $.each($(el).children(), function(key, item){
                self.checkOs(item);
            });

            if(self.matchedOs != ''){
                $('.FirstOs').html(self.matchedOs);
            }
        }
    };
</script>

<script>
    /*
     * This allows us to include jQuery and wait till the script has loaded before initializing the OS component
     * we need this in this example since it's such a tiny file (so document.ready is way before the script is loaded)
     * and because we aren't using any libraries like requirejs.
     */
    var script = document.createElement('script');

    function jqueryOnload(){
        osDetection.init($('.OS__List')[0]);
    }

    if(script.readyState) {  //IE
        script.onreadystatechange = function() {
            if ( script.readyState === "loaded" || script.readyState === "complete" ) {
                script.onreadystatechange = null;
                jqueryOnload();
            }
        };
    } else{//others
        script.onload = function() {
            jqueryOnload();
        }
    }
    script.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js";
    document.documentElement.appendChild(script);
</script>

<?php
/*****************************************************************************/

/*
 * Here is an example of the operatingSystemMatchingPatterns.json file:
[
  {
    "name": "Win 95",
    "searchString": "Windows 95",
    "sortOrder": "win001"
  },
  {
    "name": "Win 98",
    "searchString": "Windows 98",
    "sortOrder": "win002"
  },
  {
    "name": "Win Me",
    "searchString": "Win 9x 4.90",
    "sortOrder": "win003"
  },
  {
    "name": "Win NT 3.5",
    "searchString": "Windows NT 3.5",
    "sortOrder": "win004"
  },
  {
    "name": "Win NT 4.0",
    "searchString": "Windows NT 4.0",
    "sortOrder": "win005"
  },
  {
    "name": "Win 2000",
    "searchString": "Windows NT 5.0",
    "sortOrder": "win006"
  },
  {
    "name": "Win XP",
    "searchString": "Windows NT 5.1",
    "sortOrder": "win007-1"
  },
  {
    "name": "Win XP Media Center Edition",
    "searchString": "Windows NT 5.1",
    "sortOrder": "win007-2"
  },
  {
    "name": "Win XP Media Center Edition 2005",
    "searchString": "Windows NT 5.1",
    "sortOrder": "win007-3"
  },
  {
    "name": "Win XP SP1",
    "searchString": "Windows NT 5.1",
    "sortOrder": "win007-4"
  },
  {
    "name": "Win XP SP2",
    "searchString": "Windows NT 5.1",
    "sortOrder": "win007-5"
  },
  {
    "name": "Win 2003 Server",
    "searchString": "Windows NT 5.2",
    "sortOrder": "win008"
  },
  {
    "name": "Windows Vista",
    "searchString": "Windows NT 6.0",
    "sortOrder": "win009"
  },
  {
    "name": "Windows 7",
    "searchString": "Windows NT 6.1",
    "sortOrder": "win010"
  },
  {
    "name": "Windows 8",
    "searchString": "Windows NT (?:6.2|6.3)",
    "sortOrder": "win011"
  },
  {
    "name": "Windows 10",
    "searchString": "Windows NT 10.0",
    "sortOrder": "win012"
  },
  {
    "name": "Mac OS",
    "searchString": "Mac OS",
    "sortOrder": "a-mac1"
  },
  {
    "name": "Linux",
    "searchString": "(?:Linux|BSD)",
    "sortOrder": "b-linux1"
  }
]
 */