/*!
 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 *
 * 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.
 */
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import { actionTypes, enums } from './FlowsConstants.js';
import SequenceDiagramModelHelper from './SequenceDiagramModelHelper.js';

function baseUrl(serviceId, artifactId = '') {
    const restCatalogPrefix = Configuration.get('restCatalogPrefix');
    return `${restCatalogPrefix}/v1/catalog/services/${serviceId}/artifacts/${artifactId}`;
}

function encodeDataToBase64(dataAsString) {
    return window.btoa(dataAsString);
}

function decodeDataToBase64(encodedData) {
    return window.atob(encodedData);
}

function encodeContent(flowData) {
    let data = {
        VERSION: {
            major: 1,
            minor: 0
        },
        description: flowData.description,
        sequenceDiagramModel: flowData.sequenceDiagramModel
    };

    return encodeDataToBase64(JSON.stringify(data));
}

function decodeContent(base64Contents) {
    let description, sequenceDiagramModel;
    let payload = JSON.parse(decodeDataToBase64(base64Contents));

    if (payload.VERSION === undefined) {
        description = payload.description || 'Please, provide description...';
        sequenceDiagramModel = payload.data || payload;
        sequenceDiagramModel =
            sequenceDiagramModel.model || sequenceDiagramModel;
    } else if (payload.VERSION.major === 1) {
        description = payload.description;
        sequenceDiagramModel = payload.sequenceDiagramModel;
    }

    return {
        description,
        sequenceDiagramModel
    };
}

function createOrUpdate(flowData) {
    let createOrUpdateRequest = {
        payloadData: encodeContent(flowData),
        artifactLabel: flowData.artifactLabel || flowData.artifactName,
        artifactName: flowData.artifactName,
        artifactType: flowData.artifactType,
        artifactGroupType: enums.INFORMATIONAL,
        description: flowData.description
    };

    return RestAPIUtil.post(
        baseUrl(flowData.serviceID, flowData.uniqueId),
        createOrUpdateRequest,
        { md5: true }
    );
}

const FlowsActions = Object.freeze({
    fetchFlowArtifacts(
        dispatch,
        { artifacts, diagramType, participants, serviceID, readonly }
    ) {
        let results = [];
        if (!Object.keys(artifacts).length) {
            dispatch({
                type: actionTypes.FLOW_LIST_LOADED,
                results,
                participants,
                serviceID,
                diagramType,
                readonly
            });
            if (!readonly) {
                FlowsActions.openFlowDetailsEditor(dispatch);
            }
        } else {
            Object.keys(artifacts).forEach(artifact =>
                results.push({
                    artifactType: diagramType,
                    participants,
                    serviceID,
                    ...artifacts[artifact]
                })
            );
            dispatch({
                type: actionTypes.FLOW_LIST_LOADED,
                results,
                participants,
                serviceID,
                diagramType,
                readonly
            });
        }
    },

    fetchArtifact(dispatch, { flow }) {
        let { serviceID, uniqueId, participants } = flow;
        return RestAPIUtil.fetch(baseUrl(serviceID, uniqueId)).then(
            response => {
                let { artifactName, base64Contents } = response;
                let { sequenceDiagramModel, ...other } = decodeContent(
                    base64Contents
                );

                if (!sequenceDiagramModel) {
                    sequenceDiagramModel = SequenceDiagramModelHelper.createModel(
                        {
                            id: uniqueId,
                            name: artifactName,
                            lifelines: participants
                        }
                    );
                } else {
                    sequenceDiagramModel = SequenceDiagramModelHelper.updateModel(
                        sequenceDiagramModel,
                        {
                            name: artifactName,
                            lifelines: participants
                        }
                    );
                }

                flow = {
                    ...flow,
                    ...other,
                    uniqueId,
                    artifactName,
                    sequenceDiagramModel
                };

                dispatch({ type: actionTypes.ARTIFACT_LOADED, flow });
                FlowsActions.openFlowDiagramEditor(dispatch, { flow });
            }
        );
    },

    createOrUpdateFlow(dispatch, { flow }, isNew) {
        if (!isNew && flow.sequenceDiagramModel) {
            flow.sequenceDiagramModel = SequenceDiagramModelHelper.updateModel(
                flow.sequenceDiagramModel,
                {
                    name: flow.artifactName
                }
            );
        }
        return createOrUpdate(flow).then(response => {
            let { uniqueId, artifactLabel } = response;
            flow = { ...flow, uniqueId, artifactLabel };
            if (isNew) {
                flow.sequenceDiagramModel = SequenceDiagramModelHelper.createModel(
                    {
                        id: uniqueId,
                        name: flow.artifactName
                    }
                );
            }
            dispatch({ type: actionTypes.ADD_OR_UPDATE_FLOW, flow });
        });
    },

    deleteFlow(dispatch, { flow }) {
        return RestAPIUtil.destroy(baseUrl(flow.serviceID, flow.uniqueId)).then(
            () =>
                dispatch({
                    type: actionTypes.DELETE_FLOW,
                    flow
                })
        );
    },

    openFlowDetailsEditor(dispatch, flow) {
        dispatch({ type: actionTypes.OPEN_FLOW_DETAILS_EDITOR, flow });
    },

    closeFlowDetailsEditor(dispatch) {
        dispatch({ type: actionTypes.CLOSE_FLOW_DETAILS_EDITOR });
    },

    openFlowDiagramEditor(dispatch, { flow }) {
        dispatch({ type: actionTypes.OPEN_FLOW_DIAGRAM_EDITOR, flow });
    },

    closeFlowDiagramEditor(dispatch) {
        dispatch({ type: actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR });
    },

    reset(dispatch) {
        dispatch({ type: actionTypes.RESET });
    }
});

export default FlowsActions;
