<?php declare(strict_types=1);

require_once '../generic_includes.php';
require_once 'CandidateImporter.php';
require_once 'VisitImporter.php';
require_once 'InstrumentImporter.php';

/**
 * Minimum number of arguments needed to run this script.
 *
 * @var int
 */
const NUM_ARGS_REQUIRED = 4;

/*
 * Expected indices of parameters passed to this script via $argv
 *
 * @var int
 */
const MAPPING_ARG_INDEX  = 2;
const DATA_ARG_INDEX     = 3;
const EXCLUDED_ARG_INDEX = 4; // Used only for visit label imports

/**
 * Command line argument for the mode of data importation.
 */
const CANDIDATE_IMPORT  = 'candidate';
const INSTRUMENT_IMPORT = 'instrument';
const VISIT_IMPORT      = 'visits';

$usage = <<<USAGE
Usage: 

To import columns from a table: 

php {$argv[0]} %s <mapping.csv> <data.csv>
    <mapping.csv>   A CSV file containg columns with OLDPSCID, NEWPSCID, and
                    NEWCANDID
    <data.csv>      A CSV file containing columns with OLDPSCID,DATA


To import instrument information specifically:

php {$argv[0]} %s <mapping.csv> <data.csv>
    <mapping.csv>   A CSV file containg columns with OLDPSCID, NEWPSCID, and
                    NEWCANDID
    <data.csv>      A CSV file containing columns with instrument data. This
                    file should be created using the dataExtractor tool. The
                    filename must begin with the name of the instrument table
                    followed by an underscore.


To import session information specifically:

php {$argv[0]} %s <mapping.csv> <visits.csv> [excluded.csv]
    <mapping.csv>   A CSV file containg columns with OLDPSCID, NEWPSCID, and
                    NEWCANDID
    <visits.csv>    A CSV file containing information from the 'session' table.
                    Generated by dataExtractor.
    [excluded.txt]  Optional. A file containing Visit_labels to be excluded
                    from import. One per line.
        
 
USAGE;

$usageError = sprintf($usage, CANDIDATE_IMPORT, INSTRUMENT_IMPORT, VISIT_IMPORT);

/* BEGIN SCRIPT */

// Die if not enough arguments.
if (count($argv) < NUM_ARGS_REQUIRED) {
    die($usageError);
}

// Die if invalid execution mode supplied.
$mode = $argv[1];
if ($mode !== CANDIDATE_IMPORT
    && $mode !== VISIT_IMPORT
    && $mode !== INSTRUMENT_IMPORT
) {
    die($usageError);
}
$mappingFile = new SplFileInfo($argv[MAPPING_ARG_INDEX]);
$dataFile    = new SplFileInfo($argv[DATA_ARG_INDEX]);
// Get visit labels to exclude, if any
$excludedFile = $argv[EXCLUDED_ARG_INDEX] ?? null;

switch ($mode) {
case CANDIDATE_IMPORT:
    validateFilename($dataFile->getBasename(), 'candidate');
    $importer = new CandidateImporter($mappingFile, $dataFile);
    break;
case VISIT_IMPORT:
    validateFilename($dataFile->getBasename(), 'visits');
    if (is_null($excludedFile)) {
        $importer = new VisitImporter(
            $mappingFile,
            $dataFile,
            null,
            $lorisInstance->getDatabaseConnection(),
        );
    } else {
        $importer = new VisitImporter(
            $mappingFile,
            $dataFile,
            new SplFileInfo($excludedFile),
            $lorisInstance->getDatabaseConnection(),
        );
    }
    break;
case INSTRUMENT_IMPORT:
    $importer = new InstrumentImporter(
        $mappingFile,
        $dataFile,
        $lorisInstance->getDatabaseConnection()
    );
    break;
}


$importer->processData();
if (!$importer->sharedCandidates) {
    die("The mapping file and data file have no candidates in common.\n");
}
echo count($importer->sharedCandidates) . " candidates found.\n";

$skippedCount = count($importer->candidatesSkipped);
if ($skippedCount > 0) {
    print "Skipped processing information for $skippedCount candidate(s) " .
        "as they do not exist in the candidate table: " .
        PHP_EOL .
        implode("\n", array_map('formatBulletPoint', $importer->candidatesSkipped)) .
        PHP_EOL . PHP_EOL;
}

// Write the report to file.
$path = $config->getSetting('base') . 'project/data_import/';
if (!is_dir($path)) {
    mkdir($path);
}
$target = $path . date("Ymd-His") . '_dataImporterOutput.sql';

$report = $importer->report();

if (strlen($report) < 1) {
    die("Report empty. No SQL commands generated.\n");
}

file_put_contents($target, $report);

echo "SQL commands written to $target. Please review them before applying.\n";

// END SCRIPT

/**
 * Print a string as a bullet point.
 *
 * @param string $string To print.
 *
 * @return string A tab character, an asterisk, a space, and $string.
 */
function formatBulletPoint(string $string): string
{
    return sprintf("\t* $string");
}

/**
 * Basic validation to verify that the input file appears to have been generated
 * by the dataExtractor.php script by checking the filename.
 *
 * @param string $filename   The name of the input file.
 * @param string $startsWith A fixed string indicating that the file was likley
 *                           generated by the correct script.
 *
 * @return void
 *
 * @throws InvalidArgumentException
 */
function validateFileName(string $filename, string $startsWith): void
{
    if (strpos($filename, $startsWith) === false) {
        throw new InvalidArgumentException(
            "File $filename does not appear to have been generated by " .
            "dataExtractor.php (must start with '$startsWith')"
        );
    }
}
