﻿// ColsMember
// (c) 2025 Cris

// This is a script for Directory Opus.
// See https://www.gpsoft.com.au/endpoints/redirect.php?page=scripts for development information.

// Called by Directory Opus to initialize the script
function OnInit(initData) {
	initData.name = 'CollsMember';
	initData.version = '1.0.2';
	initData.copyright = '(c) 2025 Cris';
	initData.url = 'https://resource.dopus.com/t/memberofcollection-column-displaying-all-collections-containing-a-file/54331/5';
	initData.desc = '';
	initData.default_enable = true;
	initData.min_version = '13.12';

	initData.config = DOpus.Create.OrderedMap();
	initData.config_desc = DOpus.Create.OrderedMap();
	initData.config_groups = DOpus.Create.OrderedMap();
	AddConfig('log level', DOpus.NewVector(2, 'debug', 'standard', 'warning', 'off'), 'log level', 'General');
	AddConfig('match folder subitems', true, 'Set to True to list a collection for items whose parents are members of that collection, but no the item itself', 'General');

	function AddConfig(name, value, desc, group) {
		initData.config[name] = value;
		initData.config_desc(name) = desc;
		initData.config_groups(name) = group;
	}

}

// Called to add columns to Opus
function OnAddColumns(addColData) {
	var col = addColData.AddColumn();
	col.name = 'CollsMember';
	col.method = 'OnCollsMember';
	col.label = 'CollsMember';
	col.autogroup = true;
}
var colsObj, FSU, cols_enum;
// Implement the ColsMember column
function OnCollsMember(scriptColData) {
	var ini = new Date();

	if (!FSU) FSU = DOpus.FSUtil();
	var cols = '';
	var cols_markup = '';
	var paths = {};
	try {
		if (!colsObj) {
			GetColsObj(scriptColData.item, scriptColData.tab);
			cols_enum = new Enumerator(colsObj);
		}
		paths[scriptColData.item.def_value] = '';
		if (Script.config['match folder subitems']) {
			var path = FSU.NewPath(scriptColData.item.realpath);
			var last_path = '';
			while (path.test_parent) {
				path.Parent();
				paths[path.def_value] = '\\' + path.filepart + last_path;
				last_path = paths[path.def_value];
				// Log(1, scriptColData.item.name + ':' + last_path);
			}
		}
		cols_enum.moveFirst();
		for (; !cols_enum.atEnd(); cols_enum.moveNext()) {
			for (var i in paths) {
				if (colsObj(cols_enum.item()).Exists(i)) {
					Log(1, '"' + i + '" is in "' + cols_enum.item() + '" coll');
					cols += cols_enum.item() + paths[i] + '; ';
					cols_markup += cols_enum.item() + paths[i] + '\n';
					break;
				}
			}
		}
		cols = cols.slice(0, -2);
		cols_markup = cols_markup.slice(0, -1);
	}
	catch (err) {
		Log(3, 'Error while retrieving info:' + err.description);
	}
	scriptColData.value = cols;
	scriptColData.markup = cols_markup;
	Log(1, 'time=' + (new Date() - ini));

}

function GetColsObj(item, tab) {
	Log(1, 'Getting ColsObj...');
	colsObj = DOpus.Create().OrderedMap();
	var items = DOpus.Create().StringSet();
	if (tab) items.assign(DOpus.NewVector(tab.all));
	items.insert(item);
	ReadDir('coll://', items);
	Log(1, 'Colls:' + colsObj.length);
}

function ReadDir(folder, org_items) {
	var item;
	try {
		var items = DOpus.Create().StringSet();
		items.assign(org_items);
		Log(1, 'Reading "' + folder + '"...items:' + items.size);
		var coll_name = String(folder).slice(7);
		var folderObj = FSU.ReadDir(folder);
		while (!folderObj.complete) {
			if (items.empty) {
				Log(1, 'Skipping ' + folder + ' because all items were found');
				break;
			}
			item = folderObj.Next();
			// Log(1, coll_name + '=> item: ' + item + ';realpath: ' + item.realpath);
			if (item.realpath.def_value.indexOf('coll') == -1) {
				// Log(1, coll_name + '=>  Adding "' + item.realpath + '"');
				if (!colsObj.Exists(coll_name)) colsObj.Set(coll_name, DOpus.Create().StringSet());
				colsObj(coll_name).insert(item.realpath.def_value);
				items.erase(item.realpath.def_value);
			}
			if (item.is_dir && item.def_value.indexOf('coll') == 0) ReadDir(item, org_items);
		}
		folderObj.Close();
	}
	catch (err) {
		Log(3, 'Error reading "' + folder + '" : ' + err.description);
	}
	return;
}

function Log(level, text) {
	if (level === 4 || Script.config['log level'] < level) {
		if (level == 1) DOpus.Output('<#%vs_dragdrop_normal_action>DEBUG   => ' + text + '</#>');
		else if (level == 2) DOpus.Output('INFO    => ' + text);
		else if (level === 3) DOpus.Output('<#%vs_dragdrop_warning_action>WARNING => ' + text + '</#>');
		else DOpus.Output('ERROR   => ' + text, true);
	}
}