<?php

namespace CleantalkSP\SpbctWP\Settings;

use CleantalkSP\SpbctWP\Helpers\CSV;

class FilesScanPathExclusion
{
    private $DIR_EXCLUSION_FILE_NAME = 'spbct_directory_exclusions.txt';

    const EXTERNAL_SOURCE_UPDATE_PERIOD = 3600;

    private $instance_dir_separator = '/';

    public function __construct()
    {
        global $spbc;

        $this->instance_dir_separator = $spbc->is_windows ? '\\' : '/';
    }

    public function pathExclusionsView($exclusions)
    {
        $dirs = CSV::parseNSV($exclusions);
        $result = [];

        foreach ($dirs as $key => $dir) {
            if (substr($dir, -strlen($this->DIR_EXCLUSION_FILE_NAME)) === $this->DIR_EXCLUSION_FILE_NAME) {
                $parsed_url = parse_url($dir);
                if (isset($parsed_url['scheme'])) {
                    $dir = preg_replace('#^' . $parsed_url['scheme'] . '://#', '', $dir);
                }
                $dirs[$key] = $dir;
            }
        }

        foreach ($dirs as $dir) {
            $dir = preg_replace('#\\\\+|\/+#', '/', $dir);
            $dir = trim($dir, "/");
            $dir = str_replace('/', $this->instance_dir_separator, $dir);
            $result[] = $dir;
        }

        return implode("\n", $result);
    }

    public function pathExclusions($exclusions)
    {
        $dirs = CSV::parseNSV($exclusions);
        $result = [];

        $upload_urls = [];
        foreach ($dirs as $key => $dir) {
            if (substr($dir, -strlen($this->DIR_EXCLUSION_FILE_NAME)) === $this->DIR_EXCLUSION_FILE_NAME) {
                $upload_urls[] = $dir;
                unset($dirs[$key]);
            }
        }

        $upload_dirs = $this->getUploadDirs($upload_urls);

        $upload_dirs = array_filter($upload_dirs, function ($dir) {
            return $dir !== '';
        });

        $dirs = array_merge($dirs, $upload_dirs);
        $dirs = array_unique($dirs);

        foreach ($dirs as $dir) {
            $dir = preg_replace('#\\\\+|\/+#', '/', $dir);
            $dir = trim($dir, "/");
            $dir = str_replace('/', $this->instance_dir_separator, $dir);
            $result[] = $dir;
        }

        return implode("\n", $result);
    }

    private function getUploadDir($url)
    {
        $fetch_url = str_replace('\\', '/', $url);
        if (parse_url($fetch_url, PHP_URL_SCHEME) === null) {
            $fetch_url = 'http://' . $fetch_url;
        }

        $context = stream_context_create([
            'http' => [
                'timeout' => 5 // Timeout in seconds
            ]
        ]);
        $file_content = @file_get_contents($fetch_url, false, $context);

        return $file_content === false ? false : CSV::parseNSV($file_content);
    }

    private function getUploadDirs($urls)
    {
        $results = [];
        $upload_dirs_stat = [];

        foreach ($urls as $url) {
            $url = trim($url);
            if ($url === '') {
                continue;
            }
            $results[$url] = $this->getUploadDir($url);
        }

        foreach ($results as $dir => $dir_content) {
            if ($dir_content === false) {
                $upload_dirs_stat[$dir] = __('Unable to download content.', 'security-malware-firewall');
                unset($results[$dir]);
                continue;
            }

            $dir_content = array_filter($dir_content, function ($dir) {
                return $dir !== '';
            });

            $upload_dirs_stat[$dir] = count($dir_content);
        }

        update_option('spbc_upload_dirs_stat', $upload_dirs_stat);

        $upload_dirs_merged = [];
        foreach ($results as $dir) {
            $upload_dirs_merged = array_merge($upload_dirs_merged, array_values($dir));
        }

        return $upload_dirs_merged;
    }
}
