let _ = require("lodash");

module.exports = {
	name: "metrics",
	
	events: {
		"metrics.trace.span.start"(payload) {
			this.requests[payload.id] = payload;
			payload.spans = [];

			if (payload.parent) {
				let parent = this.requests[payload.parent];
				if (parent)
					parent.spans.push(payload.id);
			}
		},

		"metrics.trace.span.finish"(payload) {
			let item = this.requests[payload.id];
			_.assign(item, payload);

			if (!payload.parent)
				this.printRequest(payload.id);
		}
	},

	methods: {
		printRequest(id) {
			let main = this.requests[id];

			let w = 73;
			let r = _.repeat;
			let gw = 35;
			let maxTitle = w - 2 - 2 - gw - 2 - 1;

			this.logger.info(["┌", r("─", w-2), "┐"].join(""));

			let printSpanTime = (span) => {
				let time = span.duration.toFixed(2);

				let maxActionName = maxTitle - (span.level-1) * 2 - time.length - 3 - (span.fromCache ? 2 : 0) - (span.remoteCall ? 2 : 0) - (span.error ? 2 : 0);
				let actionName = span.action ? span.action.name : "";
				if (actionName.length > maxActionName) 
					actionName = _.truncate(span.action.name, { length: maxActionName });

				let strAction = [
					r("  ", span.level - 1),
					actionName,
					r(" ", maxActionName - actionName.length + 1),
					span.fromCache ? "* " : "",
					span.remoteCall ? "» " : "",
					span.error ? "× " : "",
					time,
					"ms "
				].join("");

				if (span.startTime == null || span.endTime == null) {
					this.logger.info(strAction + "! Missing invoke !");
					return;
				}

				let gstart = (span.startTime - main.startTime) / (main.endTime - main.startTime) * 100;
				let gstop = (span.endTime - main.startTime) / (main.endTime - main.startTime) * 100;

				if (_.isNaN(gstart) && _.isNaN(gstop)) {
					gstart = 0;
					gstop = 100;
				}

				let p1 = Math.round(gw * gstart / 100);
				let p2 = Math.round(gw * gstop / 100) - p1;
				let p3 = Math.max(gw - (p1 + p2), 0);

				let gauge = [
					"[",
					r(".", p1),
					r("■", p2),
					r(".", p3),
					"]"
				].join("");

				this.logger.info("│ " + strAction + gauge + " │");

				if (span.spans.length > 0)
					span.spans.forEach(spanID => printSpanTime(this.requests[spanID]));
			};

			printSpanTime(main);
			this.logger.info(["└", r("─", w-2), "┘"].join(""));			
		}
	},

	created() {
		this.requests = {};
	}
};