/*
 * 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 {word}', function(string, string2)  {
    assert.equal(_.get(this.context.responseData, string), string2.toLowerCase() == "true");
});
/**
 * @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 result list doesn't contain an element with property x which has value
 * equals to saved property y
 * @exampleFile ListItemsFilters.feature
 * @step I want to check that element in the response list with {string} equals to value of saved property {string} does not exist
 **/
Then('I want to check that element in the response list with {string} equals to value of saved property {string} does not exist', function (propertyPath, valueProperty) {
    const results = this.context.responseData.results;
    assert.equal(results.find(result => this.context[valueProperty] === _.get(result, propertyPath)), undefined);
});

/**
 * @module ResponseData
 * @description Check that the result list contains an element with property x which has value
 * equals to saved property y
 * @exampleFile ListItemsFilters.feature
 * @step I want to check that element in the response list with {string} equals to value of saved property {string} exists
 **/
Then('I want to check that element in the response list with {string} equals to value of saved property {string} exists', function(propertyPath, valueProperty) {
    const results = this.context.responseData.results;
    assert.notEqual(results.find(result => this.context[valueProperty] === _.get(result, propertyPath)), undefined);
});

/**
 * @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);
});