import process from 'process';
import os from 'os';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url'
import { execSync, spawnSync } from 'child_process';

const PKG = JSON.parse(fs.readFileSync('./package.json').toString());
const IS_FREEBSD = os.platform() === 'freebsd';
const IS_WINDOWS = os.platform() === 'win32';
const MAYOR_VERSION = PKG.version.split('.')[0];
const ZWPLAYER_LIBRARY_DIR = 'zwplayerlib/prebuild';
const __filenameCur = fileURLToPath(import.meta.url)
const __dirnameCur = path.dirname(__filenameCur);
const CURRENT_DIRECTORY = path.resolve(__dirnameCur);

const task = process.argv.slice(2).join(' ');

run();

async function run()
{
	switch (task)
	{
		case 'prepare':
		{
			logInfo('zwplayer run script prepare...');

			break;
		}
		
		case 'postinstall':
		{
			logInfo('zwplayer run script postinstall...');
			
			const project_path = path.normalize(`${CURRENT_DIRECTORY}/../..`);
			const zwplayerLibDir = `${CURRENT_DIRECTORY}/zwplayerlib/zwplayer`;
			const zwplayer_js = `${zwplayerLibDir}/zwplayer.js`;
			
			const zwplayer_js_filepath = path.normalize(zwplayer_js);

			if (!fs.existsSync(zwplayer_js_filepath))
			{
				logError(`zwplayer library file "${zwplayer_js}" does not exist.`);
				zwplayer_library_install();
				return;
			}
			
			const public_path = path.normalize(`${project_path}/public`);

			if (!fs.existsSync(public_path))
			{
				logInfo(`vue public path ${public_path} does not exist, creating it.`);
				ensureDirSync(public_path);
			}
			
			// copy files
			const source_path = path.normalize(`${CURRENT_DIRECTORY}/zwplayerlib`);
			
			copyDirectory(source_path, public_path);
			
			break;
		}
	}
}

function logInfo(message)
{
	// eslint-disable-next-line no-console
	console.log(`npm-scripts \x1b[36m[INFO] [${task}]\x1b\[0m`, message);
}

function logWarn(message)
{
	// eslint-disable-next-line no-console
	console.warn(`npm-scripts \x1b[33m[WARN] [${task}]\x1b\[0m`, message);
}

function logError(message)
{
	// eslint-disable-next-line no-console
	console.error(`npm-scripts \x1b[31m[ERROR] [${task}]\x1b\[0m`, message);
}

function exitWithError()
{
	process.exit(1);
}

function checkExistSync(path)
{
	try {
		fs.accessSync(
			path,
			fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK
		);
		// console.log(`Directory "${path}" exists.`);
		return true;
	} catch (err) {
		logInfo(`Directory "${path}" does not exist.`);
		return false;
	}
}

function ensureDirSync(dir) 
{
	const exists = fs.existsSync(dir);
	if (!exists) {

		ensureDirSync(path.dirname(dir));

		fs.mkdirSync(dir);
	}
}

function copyFile(srcFile, desFile)
{
	const _fs = fs;
	
	const destDir = path.dirname(desFile);
	
	ensureDirSync(destDir);
	
	return new Promise((resolve, reject) => {
		try {
			const writeStream = _fs.createWriteStream(desFile);
			const readStream = _fs.createReadStream(srcFile);
			readStream.on("error", reject);
			readStream.on("close", resolve);
			writeStream.on("error", reject);
			writeStream.on("finish", () => {
				console.log("File copied successfully!");
			});
			readStream.pipe(writeStream);
		} catch (error) {
			console.error(error);
		}
	});
}

async function copyDirectory(srcPath, desPath) 
{
	const _fs = fs;
	const _path = path;
	try {
		const isSrcExist = checkExistSync(srcPath);
		if (!isSrcExist) {
			logError(`copyDirectory error: ${srcPath} does not exist`);
			return;
		}
		
		const isDesExist = checkExistSync(desPath);
		if (!isDesExist) ensureDirSync(desPath);
	
		const files = _fs.readdirSync(srcPath);
		
		for (const file of files) {
			const copyPath = _path.join(srcPath, file);
			const destPath = _path.join(desPath, file);
			const stats = await _fs.statSync(copyPath);
			
			if (stats.isDirectory()) {
				await copyDirectory(copyPath, destPath);
			} else {
				await copyFile(copyPath, destPath);
			}
		}
	} catch (error) {
		console.error(`Error copying directory: ${error.message}`);
	}
}
