<commit_before><?php

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Illuminate\Support\Facades\File;
use Entities\Album;
use Entities\Image;
use Entities\Genre;
use Entities\User;
use Entities\Track;
use Commands\UploadTrackCommand;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Carbon\Carbon;

require_once(app_path() . '/library/getid3/getid3/getid3.php');


class ImportMLPMA extends Command {

	/**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'mlpma:import';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Imports the MLP Music Archive';

	/**
	 * File extensions to ignore when importing the archive.
	 *
	 * @var array
	 */
	protected $ignoredExtensions = ['db', 'jpg', 'png', 'txt', 'rtf', 'wma'];

	/**
	 * Used to stop the import process when a SIGINT is received.
	 *
	 * @var bool
	 */
	protected $isInterrupted = false;

	/**
	 * A counter for the number of processed tracks.
	 *
	 * @var int
	 */
	protected $currentFile;

	/**
	 * Create a new command instance.
	 *
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();
	}

	public function handleInterrupt($signo) {
		$this->error('Import aborted!');
		$this->error('Resume it from here using: --startAt='.$this->currentFile);
		$this->isInterrupted = true;
	}

	/**
	 * Execute the console command.
	 *
	 * @return void
	 */
	public function fire()
	{
		pcntl_signal(SIGINT, [$this, 'handleInterrupt']);

		$mlpmaPath = Config::get('app.files_directory').'mlpma';
		$tmpPath = Config::get('app.files_directory').'tmp';

		if (!File::exists($tmpPath)) {
			File::makeDirectory($tmpPath);
		}

		$UNKNOWN_GENRE = Genre::firstOrCreate([
			'name' => 'Unknown',
			'slug' => 'unknown'
		]);

		$this->comment('Enumerating MLP Music Archive source files...');
		$files = File::allFiles($mlpmaPath);
		$this->info(sizeof($files).' files found!');

		$this->comment('Enumerating artists...');
		$artists = File::directories($mlpmaPath);
		$this->info(sizeof($artists).' artists found!');

		$this->comment('Importing tracks...');

		$totalFiles = sizeof($files);

		$fileToStartAt = (int) $this->option('startAt') - 1;
		$this->comment("Skipping $fileToStartAt files...".PHP_EOL);

		$files = array_slice($files, $fileToStartAt);
		$this->currentFile = $fileToStartAt;

		foreach($files as $file) {
			$this->currentFile++;

			pcntl_signal_dispatch();
			if ($this->isInterrupted) {
				break;
			}

			$this->comment('['.$this->currentFile.'/'.$totalFiles.'] Importing track ['. $file->getFilename() .']...');

			if (in_array($file->getExtension(), $this->ignoredExtensions)) {
				$this->comment('This is not an audio file! Skipping...'.PHP_EOL);
				continue;
			}


			// Has this track already been imported?
			$importedTrack = DB::table('mlpma_tracks')
			                   ->where('filename', '=', $file->getFilename())
			                   ->first();

			if ($importedTrack) {
				$this->comment('This track has already been imported! Skipping...' . PHP_EOL);
				continue;
			}


			//==========================================================================================================
			// Extract the original tags.
			//==========================================================================================================
			$getId3 = new getID3;

			// all tags read by getID3, including the cover art
			$allTags = $getId3->analyze($file->getPathname());

			// tags specific to a file format (ID3 or Atom), pre-normalization but with cover art removed
			$rawTags = [];

			// normalized tags used by Pony.fm
			$parsedTags = [];

			if (Str::lower($file->getExtension()) === 'mp3') {
				list($parsedTags, $rawTags) = $this->getId3Tags($allTags);

			} else if (Str::lower($file->getExtension()) === 'm4a') {
				list($parsedTags, $rawTags) = $this->getAtomTags($allTags);

			} else if (Str::lower($file->getExtension()) === 'ogg') {
				list($parsedTags, $rawTags) = $this->getVorbisTags($allTags);

			} else if (Str::lower($file->getExtension()) === 'flac') {
				list($parsedTags, $rawTags) = $this->getVorbisTags($allTags);

			}


			//==========================================================================================================
			// Determine the release date.
			//==========================================================================================================
			$modifiedDate = Carbon::createFromTimeStampUTC(File::lastModified($file->getPathname()));
			$taggedYear = $parsedTags['year'];

			$this->info('Modification year: '.$modifiedDate->year);
			$this->info('Tagged year: '.$taggedYear);

			if ($taggedYear !== null && $modifiedDate->year === $taggedYear) {
				$releasedAt = $modifiedDate;

			} else if ($taggedYear !== null && (string) Str::length($taggedYear) !== 4) {
				$this->error('This track\'s tagged year makes no sense! Using the track\'s last modified date...');
				$releasedAt = $modifiedDate;

			} else if ($taggedYear !== null && $modifiedDate->year !== $taggedYear) {
				$this->error('Release years don\'t match! Using the tagged year...');
				$releasedAt = Carbon::create($taggedYear);

			} else {
				// $taggedYear is null
				$this->error('This track isn\'t tagged with its release year! Using the track\'s last modified date...');
				$releasedAt = $modifiedDate;
			}

			// This is later used by the classification/publishing script to determine the publication date.
			$parsedTags['released_at'] = $releasedAt->toDateTimeString();

			//==========================================================================================================
			// Does this track have vocals?
			//==========================================================================================================
			$isVocal = $parsedTags['lyrics'] !== null;


			//==========================================================================================================
			// Fill in the title tag if it's missing.
			//==========================================================================================================<commit_msg>T357: Put the string cast in the right place.<commit_after><?php

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Illuminate\Support\Facades\File;
use Entities\Album;
use Entities\Image;
use Entities\Genre;
use Entities\User;
use Entities\Track;
use Commands\UploadTrackCommand;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Carbon\Carbon;

require_once(app_path() . '/library/getid3/getid3/getid3.php');


class ImportMLPMA extends Command {

	/**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'mlpma:import';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Imports the MLP Music Archive';

	/**
	 * File extensions to ignore when importing the archive.
	 *
	 * @var array
	 */
	protected $ignoredExtensions = ['db', 'jpg', 'png', 'txt', 'rtf', 'wma'];

	/**
	 * Used to stop the import process when a SIGINT is received.
	 *
	 * @var bool
	 */
	protected $isInterrupted = false;

	/**
	 * A counter for the number of processed tracks.
	 *
	 * @var int
	 */
	protected $currentFile;

	/**
	 * Create a new command instance.
	 *
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();
	}

	public function handleInterrupt($signo) {
		$this->error('Import aborted!');
		$this->error('Resume it from here using: --startAt='.$this->currentFile);
		$this->isInterrupted = true;
	}

	/**
	 * Execute the console command.
	 *
	 * @return void
	 */
	public function fire()
	{
		pcntl_signal(SIGINT, [$this, 'handleInterrupt']);

		$mlpmaPath = Config::get('app.files_directory').'mlpma';
		$tmpPath = Config::get('app.files_directory').'tmp';

		if (!File::exists($tmpPath)) {
			File::makeDirectory($tmpPath);
		}

		$UNKNOWN_GENRE = Genre::firstOrCreate([
			'name' => 'Unknown',
			'slug' => 'unknown'
		]);

		$this->comment('Enumerating MLP Music Archive source files...');
		$files = File::allFiles($mlpmaPath);
		$this->info(sizeof($files).' files found!');

		$this->comment('Enumerating artists...');
		$artists = File::directories($mlpmaPath);
		$this->info(sizeof($artists).' artists found!');

		$this->comment('Importing tracks...');

		$totalFiles = sizeof($files);

		$fileToStartAt = (int) $this->option('startAt') - 1;
		$this->comment("Skipping $fileToStartAt files...".PHP_EOL);

		$files = array_slice($files, $fileToStartAt);
		$this->currentFile = $fileToStartAt;

		foreach($files as $file) {
			$this->currentFile++;

			pcntl_signal_dispatch();
			if ($this->isInterrupted) {
				break;
			}

			$this->comment('['.$this->currentFile.'/'.$totalFiles.'] Importing track ['. $file->getFilename() .']...');

			if (in_array($file->getExtension(), $this->ignoredExtensions)) {
				$this->comment('This is not an audio file! Skipping...'.PHP_EOL);
				continue;
			}


			// Has this track already been imported?
			$importedTrack = DB::table('mlpma_tracks')
			                   ->where('filename', '=', $file->getFilename())
			                   ->first();

			if ($importedTrack) {
				$this->comment('This track has already been imported! Skipping...' . PHP_EOL);
				continue;
			}


			//==========================================================================================================
			// Extract the original tags.
			//==========================================================================================================
			$getId3 = new getID3;

			// all tags read by getID3, including the cover art
			$allTags = $getId3->analyze($file->getPathname());

			// tags specific to a file format (ID3 or Atom), pre-normalization but with cover art removed
			$rawTags = [];

			// normalized tags used by Pony.fm
			$parsedTags = [];

			if (Str::lower($file->getExtension()) === 'mp3') {
				list($parsedTags, $rawTags) = $this->getId3Tags($allTags);

			} else if (Str::lower($file->getExtension()) === 'm4a') {
				list($parsedTags, $rawTags) = $this->getAtomTags($allTags);

			} else if (Str::lower($file->getExtension()) === 'ogg') {
				list($parsedTags, $rawTags) = $this->getVorbisTags($allTags);

			} else if (Str::lower($file->getExtension()) === 'flac') {
				list($parsedTags, $rawTags) = $this->getVorbisTags($allTags);

			}


			//==========================================================================================================
			// Determine the release date.
			//==========================================================================================================
			$modifiedDate = Carbon::createFromTimeStampUTC(File::lastModified($file->getPathname()));
			$taggedYear = $parsedTags['year'];

			$this->info('Modification year: '.$modifiedDate->year);
			$this->info('Tagged year: '.$taggedYear);

			if ($taggedYear !== null && $modifiedDate->year === $taggedYear) {
				$releasedAt = $modifiedDate;

			} else if ($taggedYear !== null && Str::length((string) $taggedYear) !== 4) {
				$this->error('This track\'s tagged year makes no sense! Using the track\'s last modified date...');
				$releasedAt = $modifiedDate;

			} else if ($taggedYear !== null && $modifiedDate->year !== $taggedYear) {
				$this->error('Release years don\'t match! Using the tagged year...');
				$releasedAt = Carbon::create($taggedYear);

			} else {
				// $taggedYear is null
				$this->error('This track isn\'t tagged with its release year! Using the track\'s last modified date...');
				$releasedAt = $modifiedDate;
			}

			// This is later used by the classification/publishing script to determine the publication date.
			$parsedTags['released_at'] = $releasedAt->toDateTimeString();

			//==========================================================================================================
			// Does this track have vocals?
			//==========================================================================================================
			$isVocal = $parsedTags['lyrics'] !== null;


			//==========================================================================================================
			// Fill in the title tag if it's missing.
			//==========================================================================================================
{'fraction_non_alphanumeric': 0.28713986801867053, 'fraction_numerical': 0.0023338161918557863, 'mean_word_length': 4.27909940526763, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '490650', 'n_tokens_mistral': 4067, 'n_tokens_neox': 3462, 'n_words': 816}