// Copyright (c) 2015, JINGROW and Contributors
// MIT License. See license.txt

Object.assign(jingrow.model, {
	pageinfo: {},
	sync: function (r) {
		/* pgs:
			extract pgs, pageinfo (attachments, comments, assignments)
			from incoming request and set in `locals` and `jingrow.model.pageinfo`
		*/
		var isPlain;
		if (!r.pgs && !r.pageinfo) r = { pgs: r };

		isPlain = $.isPlainObject(r.pgs);
		if (isPlain) r.pgs = [r.pgs];

		if (r.pgs) {
			for (var i = 0, l = r.pgs.length; i < l; i++) {
				var d = r.pgs[i];

				if (locals[d.pagetype] && locals[d.pagetype][d.name]) {
					// update values
					jingrow.model.update_in_locals(d);
				} else {
					jingrow.model.add_to_locals(d);
				}

				d.__last_sync_on = new Date();

				if (d.pagetype === "PageType") {
					jingrow.meta.sync(d);
				}

				if (d.localname) {
					jingrow.model.rename_after_save(d, i);
				}
			}
		}

		jingrow.model.sync_pageinfo(r);
		return r.pgs;
	},

	rename_after_save: (d, i) => {
		jingrow.model.new_names[d.localname] = d.name;
		$(document).trigger("rename", [d.pagetype, d.localname, d.name]);
		delete locals[d.pagetype][d.localname];

		// update pageinfo to new dict keys
		if (i === 0) {
			jingrow.model.pageinfo[d.pagetype][d.name] = jingrow.model.pageinfo[d.pagetype][d.localname];
			jingrow.model.pageinfo[d.pagetype][d.localname] = undefined;
		}
	},

	sync_pageinfo: (r) => {
		// set pageinfo (comments, assign, attachments)
		if (r.pageinfo) {
			const { pagetype, name } = r.pageinfo;
			if (!jingrow.model.pageinfo[pagetype]) {
				jingrow.model.pageinfo[pagetype] = {};
			}
			jingrow.model.pageinfo[pagetype][name] = r.pageinfo;

			// copy values to jingrow.boot.user_info
			Object.assign(jingrow.boot.user_info, r.pageinfo.user_info);
		}

		return r.pgs;
	},

	add_to_locals: function (pg) {
		if (!locals[pg.pagetype]) locals[pg.pagetype] = {};

		if (!pg.name && pg.__islocal) {
			// get name (local if required)
			if (!pg.parentfield) jingrow.model.clear_pg(pg);

			pg.name = jingrow.model.get_new_name(pg.pagetype);

			if (!pg.parentfield)
				jingrow.provide("jingrow.model.pageinfo." + pg.pagetype + "." + pg.name);
		}

		locals[pg.pagetype][pg.name] = pg;

		let meta = jingrow.get_meta(pg.pagetype);
		let is_table = meta ? meta.istable : pg.parentfield;
		// add child pgs to locals
		if (!is_table) {
			for (var i in pg) {
				var value = pg[i];

				if ($.isArray(value)) {
					for (var x = 0, y = value.length; x < y; x++) {
						var d = value[x];

						if (typeof d == "object" && !d.parent) d.parent = pg.name;

						jingrow.model.add_to_locals(d);
					}
				}
			}
		}
	},

	update_in_locals: function (pg) {
		// update values in the existing local pg instead of replacing
		let local_pg = locals[pg.pagetype][pg.name];
		let clear_keys = function (source, target) {
			Object.keys(target).map((key) => {
				if (source[key] == undefined) delete target[key];
			});
		};

		for (let fieldname in pg) {
			let df = jingrow.meta.get_field(pg.pagetype, fieldname);
			if (df && jingrow.model.table_fields.includes(df.fieldtype)) {
				// table
				if (!(pg[fieldname] instanceof Array)) {
					pg[fieldname] = [];
				}

				if (!(local_pg[fieldname] instanceof Array)) {
					local_pg[fieldname] = [];
				}

				// child table, override each row and append new rows if required
				for (let i = 0; i < pg[fieldname].length; i++) {
					let d = pg[fieldname][i];
					let local_d = local_pg[fieldname][i];
					if (local_d) {
						// deleted and added again
						if (!locals[d.pagetype]) locals[d.pagetype] = {};

						if (!d.name) {
							// incoming row is new, find a new name
							d.name = jingrow.model.get_new_name(pg.pagetype);
						}

						// if incoming row is not registered, register it
						if (!locals[d.pagetype][d.name]) {
							// detach old key
							delete locals[d.pagetype][local_d.name];

							// re-attach with new name
							locals[d.pagetype][d.name] = local_d;
						}

						// row exists, just copy the values
						Object.assign(local_d, d);
						clear_keys(d, local_d);
					} else {
						local_pg[fieldname].push(d);
						if (!d.parent) d.parent = pg.name;
						jingrow.model.add_to_locals(d);
					}
				}

				// remove extra rows
				if (local_pg[fieldname].length > pg[fieldname].length) {
					for (let i = pg[fieldname].length; i < local_pg[fieldname].length; i++) {
						// clear from local
						let d = local_pg[fieldname][i];
						if (locals[d.pagetype] && locals[d.pagetype][d.name]) {
							delete locals[d.pagetype][d.name];
						}
					}
					local_pg[fieldname].length = pg[fieldname].length;
				}
			} else {
				// literal
				local_pg[fieldname] = pg[fieldname];
			}
		}

		// clear keys on parent
		clear_keys(pg, local_pg);
	},
});
