<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\{Flag,Node,Zone};

class ImportNodelist extends Command
{
	/**
	 * The name and signature of the console command.
	 *
	 * @var string
	 */
	protected $signature = 'import:nodelist {file : Nodelist File}';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Import Nodelist';

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

	/**
	 * Execute the console command.
	 *
	 * @return mixed
	 */
	public function handle()
	{
		$file = $this->argument('file');
		$lines = intval(exec("wc -l '$file'"));

		$file = fopen($file,"r");
		$bar = $this->output->createProgressBar($lines);
		$bar->setFormat("%current%/%max% [%bar%] %percent:3s%% (%memory%) (%remaining%) ");
		$bar->setRedrawFrequency(100);
		$bar->start();

		$zone = $region = $host = NULL;

		while (! feof($file)) {
			$line = stream_get_line($file, 0, "\r\n");

			// Lines beginning with a semicolon(;) are comments
			if (preg_match('/^;/',$line) OR ($line == chr(0x1A)))
				continue;

			$fields = explode(',',$line);

			$o = new Node();

			// First field is either zone,region,host,hub,down,pvt (or blank)
			if ($fields[0] AND ! in_array($fields[0],['Zone','Region','Host','Hub','Pvt','Down']))
			{
				$this->error(sprintf('Invalid field zero [%s] - IGNORING record (%s)',$fields[0],$line));
				$bar->advance();
				continue;
			}

			$status = NULL;
			$node = 0;

			switch ($fields[0])
			{
				case 'Zone': $zone = $fields[1];
					$zo = Zone::firstOrCreate([
						'id'=>$zone
					]);
				break;
				case 'Host': $host = $fields[1]; break;
				case 'Region': $region = $fields[1]; break;

				case 'Down':
				case 'Pvt': $status = $fields[0];
				case '':
					$node = $fields[1];
					break;

				default:
					$this->error(sprintf('Unhandled first field [%s]',$fields[0]));
					$bar->advance();
					continue 2;
			}

			if (! $zone)
			{
				$this->error('Zone NOT set, ignoring record...');
				$bar->advance();
				continue;
			}

			if (! $host)
			{
				$host = $zone;
			}

			if (! $region)
			{
				$region = 0 ;
			}

			$o = Node::firstOrNew([
				'zone_id'=>$zo->id,
				'host_id'=>$host,
				'node_id'=>$node,
			]);

			$o->region_id = $region;
			$o->system = $fields[2];
			$o->location = $fields[3];
			$o->sysop = $fields[4];
			$o->active = TRUE;
			$o->status = $status;

			if (! in_array($fields[5],['-Unpublished-']))
				$o->phone = $fields[5];

			$o->baud = $fields[6];
			$o->save();

			// Fields 7 onwards are flags
			$flags = collect();
			for ($i=7;$i<count($fields);$i++)
			{
				$value = NULL;
				if (preg_match('/^[A-Z]+:/',$fields[$i]))
				{
					list($flag,$value) = explode(':',$fields[$i],2);
				} else {
					$flag = $fields[$i];
				}

				$fo = Flag::firstOrNew(
					['flag'=>$flag]
				);

				if (! $flag)
				{
					$this->warn('Ignoring blank flag on: '.$line);
					continue;
				}

				if (! $fo->exists)
				{
					$fo->description = 'Auto Created on Import';
					$fo->save();
				}

				$flags->put($fo->id,['arguments'=>$value]);
			}

			$o->flags()->sync($flags);

			$bar->advance();
		}

		fclose($file);
		$bar->finish();
		echo "\n";
	}
}