/*
 * Copyright © 2016-2017 European Support Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const {Then, When, Given} = require('cucumber');
const assert = require('assert');
const _ = require('lodash');
const normalizeNewline = require('normalize-newline');
require('node-zip');
YAML = require('yamljs');
const fs = require('fs');
const util = require('./Utils.js');

function getPath(path, context) {
	let compiled = _.template(path);
	return compiled(context);
}

/**
 * @module ContextData
 * @description  Use with "Given". Use ONLY for local testing when you know the value of the Item you want to use
 * instead of creating a new one.
 * @step Item {string} and version Id {string}
 **/
Given('Item {string} and version Id {string}', function (string, string2) {
	this.context.item.id = string;
	this.context.item.versionId = string2;
});
/**
 * @module ContextData
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @description Response Data::<br>
 *     """<br>
 *         {jsonObject}<br>
 *             """<br>
 * @step  Use with "Given". Use ONLY for local testing, creates a response data object
 **/
Given('Response Data:', function (docString) {
	this.context.responseData = JSON.parse(docString);
});

/**
 * @module ContextData
 * @description Copy a property from the response data to context Item/VLM/VSP data, example: vsp.componentId
 * @step I want to save on the context for {string} property {string} with value {string}
 **/
Then('I want to save on the context for {string} property {string} with value {string}', function(string, string1, string2)  {
	assert.equal(_.includes(['VLM', 'VSP', 'Item'], string), true);
	let val = _.get(this.context.responseData, string2);
	_.set(this.context, string1, val);
});
/**
 * @module ContextData
 * @description Copy a property from the response data to saved data on the context. Example: save newly generated IDs. Response data value can be from a path, xample: results[0].id
 * @exampleFile Example_Rest_Calls.feature
 * @step I want to save to property {string} from response data path {string}
 **/
Then('I want to copy to property {string} from response data path {string}', function(string, string2)  {
	let val = _.get(this.context.responseData, string2);
	_.set(this.context, string, val);
});
/**
 * @module ContextData
 * @description This will set the value of a saved property on the context
 * @exampleFile Example_Rest_Calls.feature
 * @step I want to set property {string} to value {string}
 **/
Then('I want to set property {string} to value {string}', function(string, string2)  {
	_.set(this.context, string, string2);
});

/**
 * @module ResponseData
 * @description Will check the output data for a property and a value. property can be a path (example: results[0].id)
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @step I want to check property {string} for value {string}
 **/
Then('I want to check property {string} for value {string}', function(string, string2)  {
	assert.equal(_.get(this.context.responseData, string), string2);
});
/**
 * @module ResponseData
 * @description Will check the output data for a property and a value. property can be a path
 * (example: results[0].id). Supports comparison to a long String by allowing a line break
 * @exampleFile VirtualMachineInterfaceValidationHeatResourceMissingProperties.feature
 * @step I want to check property {string} for value {string}
 **/

Then('I want to check property {string} for value:', function(string, docString)  {
	assert.equal(_.get(this.context.responseData, string), docString.trim());
});
/**
 * @module ResponseData
 * @description Will check the output data for a property and a integer. property can be a path (example: results[0].id)
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @step I want to check property {string} for value {int}
 **/
Then('I want to check property {string} for value {int}', function(string, int)  {
	assert.equal(_.get(this.context.responseData, string), int);
});
/**
 * @module ResponseData
 * @description Will check the output data for a property and a boolean. property can be a path (example: results[0].id)
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @step I want to check property {string} to be "True/False"
 **/
Then('I want to check property {string} to be {string}', function(string, string2)  {
	assert.equal(_.get(this.context.responseData, string), string2.toLowerCase());
});
/**
 * @module ResponseData
 * @description Will check the output data for a property and a boolean. property can be a path (example: results[0].id)
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @step I want to check property {string} to have length {int}
 **/
Then('I want to check property {string} to have length {int}', function(string, intLength)  {
	let arrayProp = _.get(this.context.responseData, string);
	assert.equal(arrayProp.length, intLength);
});
/**
 * @module ResponseData
 * @description Will check the output data for a property and make sure it exists
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @step I want to check property {string} exists
 **/
Then('I want to check property {string} exists', function(string)  {
	assert.equal(_.has(this.context.responseData, string), true);
});
/**
 * @module ResponseData
 * @description Will check the output data for a property and make sure it does not exist
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
 * @step I want to check property {string} does not exist
 **/
Then('I want to check property {string} does not exist', function(string)  {
	assert.equal(_.has(this.context.responseData, string), false);
});

/**
* @module ContextData
* @description Use during development to see what is on the context
 * @exampleFile Example_ResponseData_CheckAndManipulation.feature
* @step I want to print context data
**/
Then('I want to print the context data', function()  {
	console.log('------------ context ---------------');
	console.log(JSON.stringify(this.context, null, 2));
	console.log('--------------------------------------');
});
/**
 * @module ContextData
 * @description Set this in order to check that the following Rest call will not have response code 200
 * @exampleFile Example_Rest_Calls.feature
 * @step I want the following to fail
 **/
Then('I want the following to fail', function()  {
	this.context.shouldFail = true;
});

/**
 * @module ContextData
 * @description Set this in order to check that the following Rest call will have the error code on the return data
 * @exampleFile Example_VSP.feature
 * @step I want the following to fail with error code {string}
 **/
Then('I want the following to fail with error code {string}', function(string)  {
	this.context.shouldFail = true;
	this.context.errorCode = string;
});


/**
 * @module ContextData
 * @description Set this in order to check that the following Rest call will have the error message on the return data
 * @exampleFile DeleteVLMCertified.feature
 * @step I want the following to fail with error message {string}
 **/
Then('I want the following to fail with error message {string}', function(string)  {
	this.context.shouldFail = true;
	let errorMessage = getPath(string, this.context);
	this.context.errorMessage = errorMessage;
});

/**
 * @module ZipData
 * @description Use this in order to extract a file from a zip file and to compare it to a local file (string comparison).
 * @exampleFile Example_VSP.feature
 * @step I want to compare the content of the entry {string} in the zip {string} with file {string}
 **/
Then ('I want to compare the content of the entry {string} in the zip {string} with file {string}', function (string, string2, string3) {
	let zipFile = fs.readFileSync(string2, 'binary');
	let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
	let fileData = zip.files[string]._data;
	let compareFileData = fs.readFileSync(string3, {encoding: 'ascii'});
	assert.equal(normalizeNewline(compareFileData), normalizeNewline(fileData));
});

/**
 * @module ZipData
 * @description Loads the yaml from zip file onto the context responseData as JSON for running checks on the output
 * @exampleFile Example_VSP.feature
 * @step I want to load the yaml content of the entry {string} in the zip {string} to context
 **/
Then ('I want to load the yaml content of the entry {string} in the zip {string} to context', function (string, string2, callback) {
	let zipFile = fs.readFileSync(string2, 'binary');
	let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
	let fileData = zip.files[string]._data;
	let nativeObject = YAML.parse(fileData);
	this.context.responseData = nativeObject;
	callback();
});


/**
 * @module ZipData
 * @description Loads the json from zip file onto the context responseData for running check son the output
 * @exampleFile Example_VSP.feature
 * @step I want to load the json content of the entry {string} in the zip {string} to context
 **/
When('I want to load the json content of the entry {string} in the zip {string} to context', function (string, string2, callback) {
	let zipFile = fs.readFileSync(string2, 'binary');
	let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
	let str = zip.files[string]._data;
	this.context.responseData = JSON.parse(str);
	callback();
});

/**
 * @module ResponseData
 * @description Check that the itemId from context exits in result of responseData
 * exampleFile ArchiveItem.feature
 * step I want to check that item exits in response
 **/
Then('I want to check that item exits in response', function() {

  const id = this.context.item.id;
  const results = this.context.responseData.results;
  var testResult = false;

  for(var i=0; i< results.length; i++){
     if ( id == results[i].id){
            testResult = true;
     }
  }

   assert.equal(testResult,true);
});


/**
 * @module ResponseData
 * @description Check that the itemId from context does NOT exits in result of responseData
 * exampleFile ArchiveItem.feature
 * step I want to check that item does not exits in response
 **/
Then('I want to check that item does not exits in response', function() {

  const id = this.context.item.id;
  const results = this.context.responseData.results;
  var testResult = false;

  for(var i=0; i< results.length; i++){
     if ( id == results[i].id){
            testResult = true;
     }
  }

   assert.equal(testResult,false);
});