/**
 * Poll all eligible labs for new results and store them in the database.
 *
 * @param  array   &$info  Conveys information to and from the caller:
 * FROM THE CALLER:
 * $info["$ppid/$filename"]['delete'] = a non-empty value if file deletion is requested.
 * $info['select'] = array of patient matching responses where key is serialized patient
 *   attributes and value is selected pid for this patient, or 0 to create the patient.
 * TO THE CALLER:
 * $info["$ppid/$filename"]['mssgs'] = array of messages from this function.
 * $info['match'] = array of patient matching requests where key is serialized patient
 *   attributes (ss, fname, lname, DOB) and value is TRUE (irrelevant).
 *
 * @return string  Error text, or empty if no errors.
 */
function poll_hl7_results(&$info)
{
    global $srcdir;
    // echo "<!-- post: "; print_r($_POST); echo " -->\n"; // debugging
    // echo "<!-- in:   "; print_r($info); echo " -->\n"; // debugging
    $filecount = 0;
    $badcount = 0;
    if (!isset($info['match'])) {
        $info['match'] = array();
    }
    // match requests
    if (!isset($info['select'])) {
        $info['select'] = array();
    }
    // match request responses
    $ppres = sqlStatement("SELECT * FROM procedure_providers ORDER BY name");
    while ($pprow = sqlFetchArray($ppres)) {
        $ppid = $pprow['ppid'];
        $protocol = $pprow['protocol'];
        $remote_host = $pprow['remote_host'];
        $hl7 = '';
        if ($protocol == 'SFTP') {
            $remote_port = 22;
            // Hostname may have ":port" appended to specify a nonstandard port number.
            if ($i = strrpos($remote_host, ':')) {
                $remote_port = 0 + substr($remote_host, $i + 1);
                $remote_host = substr($remote_host, 0, $i);
            }
            // Compute the target path name.
            $pathname = '.';
            if ($pprow['results_path']) {
                $pathname = $pprow['results_path'] . '/' . $pathname;
            }
            // Connect to the server and enumerate files to process.
            $sftp = new \phpseclib\Net\SFTP($remote_host, $remote_port);
            if (!$sftp->login($pprow['login'], $pprow['password'])) {
                return xl('Login to remote host') . " '{$remote_host}' " . xl('failed');
            }
            $files = $sftp->nlist($pathname);
            foreach ($files as $file) {
                if (substr($file, 0, 1) == '.') {
                    continue;
                }
                ++$filecount;
                if (!isset($info["{$ppid}/{$file}"])) {
                    $info["{$ppid}/{$file}"] = array();
                }
                // Ensure that archive directory exists.
                $prpath = $GLOBALS['OE_SITE_DIR'] . "/procedure_results";
                if (!file_exists($prpath)) {
                    mkdir($prpath);
                }
                $prpath .= '/' . $pprow['ppid'];
                if (!file_exists($prpath)) {
                    mkdir($prpath);
                }
                // Get file contents.
                $hl7 = $sftp->get("{$pathname}/{$file}");
                // If user requested reject and delete, do that.
                if (!empty($info["{$ppid}/{$file}"]['delete'])) {
                    $fh = fopen("{$prpath}/{$file}.rejected", 'w');
                    if ($fh) {
                        fwrite($fh, $hl7);
                        fclose($fh);
                    } else {
                        return xl('Cannot create file') . ' "' . "{$prpath}/{$file}.rejected" . '"';
                    }
                    if (!$sftp->delete("{$pathname}/{$file}")) {
                        return xl('Cannot delete (from SFTP server) file') . ' "' . "{$pathname}/{$file}" . '"';
                    }
                    continue;
                }
                // Do a dry run of its contents and check for errors and match requests.
                $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], true, $info['select']);
                $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs'];
                // $info["$ppid/$file"]['match'] = $tmp['match'];
                if (!empty($tmp['fatal']) || !empty($tmp['needmatch'])) {
                    // There are errors or matching requests so skip this file.
                    continue;
                }
                // Now the money shot - not a dry run.
                $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], false, $info['select']);
                $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs'];
                // $info["$ppid/$file"]['match'] = $tmp['match'];
                if (empty($tmp['fatal']) && empty($tmp['needmatch'])) {
                    // It worked, archive and delete the file.
                    $fh = fopen("{$prpath}/{$file}", 'w');
                    if ($fh) {
                        fwrite($fh, $hl7);
                        fclose($fh);
                    } else {
                        return xl('Cannot create file') . ' "' . "{$prpath}/{$file}" . '"';
                    }
                    if (!$sftp->delete("{$pathname}/{$file}")) {
                        return xl('Cannot delete (from SFTP server) file') . ' "' . "{$pathname}/{$file}" . '"';
                    }
                }
            }
            // end of this file
        } else {
            if ($protocol == 'FS') {
                // Filesystem directory containing results files.
                $pathname = $pprow['results_path'];
                if (!($dh = opendir($pathname))) {
                    return xl('Unable to access directory') . " '{$pathname}'";
                }
                // Sort by filename just because.
                $files = array();
                while (false !== ($file = readdir($dh))) {
                    if (substr($file, 0, 1) == '.') {
                        continue;
                    }
                    $files[$file] = $file;
                }
                closedir($dh);
                ksort($files);
                // For each file...
                foreach ($files as $file) {
                    ++$filecount;
                    if (!isset($info["{$ppid}/{$file}"])) {
                        $info["{$ppid}/{$file}"] = array();
                    }
                    // Ensure that archive directory exists.
                    $prpath = $GLOBALS['OE_SITE_DIR'] . "/procedure_results";
                    if (!file_exists($prpath)) {
                        mkdir($prpath);
                    }
                    $prpath .= '/' . $pprow['ppid'];
                    if (!file_exists($prpath)) {
                        mkdir($prpath);
                    }
                    // Get file contents.
                    $hl7 = file_get_contents("{$pathname}/{$file}");
                    // If user requested reject and delete, do that.
                    if (!empty($info["{$ppid}/{$file}"]['delete'])) {
                        $fh = fopen("{$prpath}/{$file}.rejected", 'w');
                        if ($fh) {
                            fwrite($fh, $hl7);
                            fclose($fh);
                        } else {
                            return xl('Cannot create file') . ' "' . "{$prpath}/{$file}.rejected" . '"';
                        }
                        if (!unlink("{$pathname}/{$file}")) {
                            return xl('Cannot delete file') . ' "' . "{$pathname}/{$file}" . '"';
                        }
                        continue;
                    }
                    // Do a dry run of its contents and check for errors and match requests.
                    $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], true, $info['select']);
                    $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs'];
                    // $info["$ppid/$file"]['match'] = $tmp['match'];
                    if (!empty($tmp['fatal']) || !empty($tmp['needmatch'])) {
                        // There are errors or matching requests so skip this file.
                        continue;
                    }
                    // Now the money shot - not a dry run.
                    $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], false, $info['select']);
                    $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs'];
                    // $info["$ppid/$file"]['match'] = $tmp['match'];
                    if (empty($tmp['fatal']) && empty($tmp['needmatch'])) {
                        // It worked, archive and delete the file.
                        $fh = fopen("{$prpath}/{$file}", 'w');
                        if ($fh) {
                            fwrite($fh, $hl7);
                            fclose($fh);
                        } else {
                            return xl('Cannot create file') . ' "' . "{$prpath}/{$file}" . '"';
                        }
                        if (!unlink("{$pathname}/{$file}")) {
                            return xl('Cannot delete file') . ' "' . "{$pathname}/{$file}" . '"';
                        }
                    }
                }
                // end of this file
            }
        }
        // end FS protocol
        // TBD: Insert "else if ($protocol == '???') {...}" to support other protocols.
    }
    // end procedure provider
    // echo "<!-- out: "; print_r($info); echo " -->\n"; // debugging
    return '';
}