import * as Redux from 'redux';
import * as Immer from 'immer'
import * as Shared from 'placeholder-shared'
import * as Common from './common'

export enum InputLocationType {
    query = 'queryParams',
    path =  'pathParams',
	header = 'headerParams',
	body = 'body'
}
//ParameterFuncs API 
export class ParameterFuncs {
	onNewRow:(e:any)=> void;
	onDeleteParameter:(index:number) => void;
	onEditParameter:(index:number, key:string, newValue:string|boolean)=> void
	onCheckChange:(index:number,newValue:boolean) => void;
}
export const getParameterFuncs = (stepCounter:number, dispatch:Function, inputLocationType:InputLocationType ):ParameterFuncs => {
	return {
		'onNewRow': (e: any) => {
			dispatch(createParameter(stepCounter, inputLocationType))
		},
		'onDeleteParameter': (index) => {
			dispatch(deleteParameter(stepCounter, inputLocationType, index))
		},
		'onEditParameter': (index, key, newValue: string|boolean) => {
			dispatch(editParameterValue(stepCounter, inputLocationType, index, key, newValue))
		},
		'onCheckChange': (index:number, newValue: boolean) => {
			dispatch(editParameterValue(stepCounter, inputLocationType, index, 'enabled', newValue))
		}
	}
}

//Parameter Funcs
export const onOperationChange = (stepCounter:number, key:string|(number|string)[], value:object | string| boolean, keepRunResult:boolean) => {
	return (dispatch, getState) => {
		let currentState = getState()
		dispatch(Shared.State.getUpdateStepOperationAction(stepCounter, key, value, keepRunResult))
	}
}

export const createParameter = (stepCounter:number, inputLocation:InputLocationType) => {
        return (dispatch, getState) => {
            let currentStepData = getState()['steps'][stepCounter]
            let inputs = currentStepData['operation']['inputs']
            let newState = {
                ...inputs,
                [inputLocation]: [
                    ...inputs[inputLocation],
                    //new Shared.Steps.RestInput()
                ]
            }
            dispatch(onOperationChange(stepCounter, 'inputs', newState, false))
        }
}

export const deleteParameter = (stepCounter:number, 
    inputLocation:InputLocationType, 
    index:number) => {
        return (dispatch, getState) => {
            let currentStepData = getState()['steps'][stepCounter]
            let inputsCopy = Object.assign({}, currentStepData['operation']['inputs']);
            inputsCopy[inputLocation].splice(index, 1);
            dispatch(onOperationChange(stepCounter, 'inputs', inputsCopy, false))
        }
}

export const editParameterValue = (stepCounter: number,
    inputLocation: InputLocationType,
    index: number,
    key:string,
    newValue: string|boolean) => {
    return (dispatch, getState) => {
		let currentRestInput = getState()['steps'][stepCounter]['operation']['inputs'][inputLocation][index]
		let newRestInput = Immer.produce(currentRestInput, (draftState) => {
			draftState[key] = newValue;
		})
        console.log("in edit parameter", currentRestInput, newRestInput)
		let editFunc = editParameter(stepCounter, inputLocation, index, newRestInput as any)
		editFunc(dispatch, getState)
    }
}

export const editParameter = (
    stepCounter: number,
    inputLocation: InputLocationType,
    index: number,
	newValue: any//Shared.Steps.RestInput
	) => {
    return (dispatch, getState) => {
        let currentStepData = getState()['steps'][stepCounter]
        let inputs = currentStepData['operation']['inputs']
        let inputsArray = inputs[inputLocation]
        let newState = {
            ...inputs,
            [inputLocation]: [
                ...inputsArray.slice(0, index), 
                newValue, 
                ...inputsArray.slice(index + 1)
            ]
        }
        console.log("in edit parameter 2", newState)
        dispatch(onOperationChange(stepCounter, 'inputs', newState, false))
    }
}


export const getPathVariables = (path:string):string[] => {
	let result = path.match(/<<(.+?)>>/g)
	if (!result)
		return []
	result = result.map((value) => {
		return value.slice(2,-2)
	})
	return result;
}

export const getQueryVariables = (path:string) => {
	let parts = path.split('?')
	if (parts.length < 2) {
		return {}
	}
	let pairs = parts[1].split('&')

	let result =  {}
	for (let i in pairs) {
		let kv = pairs[i].split('=')
		result[kv[0]] = kv[1]
	}
	return result;
}


enum AuthTypes {
	'None' = 'None' , 'Basic' = 'Basic', 'ApiKey' = 'ApiKey' , 'Bearer' = 'Bearer', 'InheritFromParent' = 'InheritFromParent'
}

export class AuthInfo{
	authType:AuthTypes = AuthTypes.InheritFromParent;
	authData:AuthData;
}
export interface AuthData{
	prepConfigWithAuth(config):any;

}
export class BasicData implements AuthData{
	username:string = "" ;
	password:string = "";
	prepConfigWithAuth(config:any){
		return config
	}
}

export enum ApiKeyLocation {
	'query'='query' ,
	'header'= 'header' 
}

export class ApiKeyData implements AuthData{
	apiKey:string = "";
	apiValue:string = "";
	location:ApiKeyLocation = ApiKeyLocation.query;
	prepConfigWithAuth(config:any){
		return config
	}
}
export class BearerTokenData implements AuthData{
	token:string = ""; 
	prepConfigWithAuth(config: any) {
	}
	clone = () => {
		let result = new BearerTokenData()
		result.token = this.token
		return result
	}
}
export const getRequestStepCounterForRequest = (taskID:number, runState:Shared.RunState.RunState) => {
	console.assert(isTaskRequest(taskID,runState ))
	return runState.treeData[taskID]['nodes'][0]['stepCounter']
}

export const isTaskRequest = (taskID:number, runState: Shared.RunState.RunState) => {
	return runState['tasks'][taskID]['request']
}

export const getReferencedOperationForStep = (runState:Shared.RunState.RunState, stepCounter:number) => {
	return null;
}

export const getTaskForRestRef = (stepCounter:number, runState:Shared.RunState.RunState) => {
}

export const getOperationForStep = (stepCounter:number, runState:Shared.RunState.RunState) => {
	return runState.steps[stepCounter].operation
}

const getCurrentOperation = (runState:Shared.RunState.RunState) => {
	return getOperationForStep(runState['currentStep'], runState)
}