const smash = require("../../../../smash.js");
const logger = smash.logger();
const errorUtil = smash.errorUtil();
const Context = require("./context.js");
const DASH = "-";

class Event {
	constructor(rawEvent, context, terminate) {
		if (typeof rawEvent !== 'object') {
			throw new errorUtil.TypeError("First parameter of Event() must be an object, ", rawEvent);
		}
		this._rawEvent = rawEvent;
		Object.assign(this, rawEvent);
		this.context = context;
		if (typeof terminate !== 'object') {
			throw new errorUtil.TypeError("Third parameter of Event() must be a object, ", terminate);
		}
		if (typeof terminate.terminate !== 'function') {
			throw new errorUtil.TypeError("Third parameter of Event() must be an object with a function called terminate, ", terminate.terminate);
		}
		if (terminate.terminate.length !== 2) {
			throw new Error("Third parameter of Event() must be an object with a function called terminate witch takes 2 parameters: error, data, " + terminate.terminate.length + " given");
		}
		if (rawEvent.requestContext) {
			Object.assign(this, rawEvent.requestContext);
		}
		this.processService();
		this.processPath();
		this._terminate = terminate;
		this.permissionContext = null;
	}

	processService() {
		if (this.domainPrefix) {
			if (this.domainPrefix.indexOf(DASH) > 0) {
				this.service = this.domainPrefix.split(DASH);
				this.service.shift();
				this.service = this.service.join(DASH);
			} else {
				this.service = this.domainPrefix;
			}
		}
		return this;
	}

	processPath() {
		const splittedPath = this.path.split("/");
		if (splittedPath[0] === this.stage) {
			splittedPath.shift();
			this.path = splittedPath.join("/");
		}
		return this;
	}

	generatePermissionContext(data) {
		this.permissionContext = new Context(data);
		return this;
	}

	_generatePolicy(effect, context) {
		const authResponse = {
			principalId: context.principalId,
			context: context.rawObject(),
		};
		if (effect && this.methodArn) {
			authResponse.policyDocument = {
				Version: '2012-10-17',
				Statement: [
					{
						Action: 'execute-api:Invoke',
						Effect: effect,
						Resource: smash.getCurrentEvent().methodArn,
					},
				],
			};
		}
		return authResponse;
	}

	terminate(error, data) {
		this._terminate.terminate(error, data);
		return this;
	}

	allow() {
		if (this.permissionContext) {
			this.terminate(null, this._generatePolicy("Allow", this.permissionContext));
		} else {
			this.internalServerError(errorUtil.internalServerError("Method generatePermissionContext(data) must be called before allow(), " + errorUtil.typeOf(this.permissionContext)));
		}
		return this;
	}

	deny() {
		if (this.permissionContext) {
			this.terminate(null, this._generatePolicy("Deny", this.permissionContext));
		} else {
			this.internalServerError(errorUtil.internalServerError("Method generatePermissionContext(data) must be called before deny(), " + errorUtil.typeOf(this.permissionContext)));
		}
		return this;
	}

	unauthorized(error) {
		if (error) {
			logger.error("Unauthorized", error);
		} else {
			logger.error("Unauthorized");
		}
		this.terminate("Unauthorized");
		return this;
	}

	internalServerError(error) {
		if (errorUtil.isSmashError(error) === false) {
			error = errorUtil.internalServerError("First argument of handleError(error) must ba a SmashError, " + errorUtil.typeOf(error), error);
		}
		error.printError();
		this.terminate("Internal server error");
		return this;
	}

	handleError(error) {
		if (errorUtil.isSmashError(error) === false) {
			error = errorUtil.internalServerError("First argument of handleError(error) must ba a SmashError, " + errorUtil.typeOf(error), error);
		}
		error.printError();
		if (errorUtil.isUnauthorizedError(error) === true) {
			this.unauthorized(error);
		} else if (errorUtil.isForbiddenError(error) === true) {
			this.deny(error);
		} else {
			this.internalServerError(error);
		}
		return this;
	}
}

module.exports = Event;

@@ -1044,35 +1044,37 @@
 t) %7B%0A%09%09%09
-Object.assign(this,
+this.requestContext =
  rawEven
@@ -1089,17 +1089,16 @@
 tContext
-)
 ;%0A%09%09%7D%0A%09%09
@@ -1124,30 +1124,8 @@
 ();%0A
-%09%09this.processPath();%0A
 %09%09th
@@ -1211,32 +1211,70 @@
 () %7B%0A%09%09if (this.
+requestContext && this.requestContext.
 domainPrefix) %7B%0A
@@ -1281,24 +1281,39 @@
 %09%09%09if (this.
+requestContext.
 domainPrefix
@@ -1350,32 +1350,47 @@
 .service = this.
+requestContext.
 domainPrefix.spl
@@ -1505,16 +1505,31 @@
  = this.
+requestContext.
 domainPr
@@ -1542,197 +1542,8 @@
 %09%09%09%7D
-%0A%09%09%7D%0A%09%09return this;%0A%09%7D%0A%0A%09processPath() %7B%0A%09%09const splittedPath = this.path.split(%22/%22);%0A%09%09if (splittedPath%5B0%5D === this.stage) %7B%0A%09%09%09splittedPath.shift();%0A%09%09%09this.path = splittedPath.join(%22/%22);
 %0A%09%09%7D

Fix bug with properties override