// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
package com.cloud.api;

import java.lang.reflect.Type;
import java.util.Map;

import javax.inject.Inject;

import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ExceptionResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.jobs.AsyncJob;
import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher;
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.jobs.JobInfo;

import com.cloud.exception.InvalidParameterValueException;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.db.EntityManager;

public class ApiAsyncJobDispatcher extends AdapterBase implements AsyncJobDispatcher {
    private static final Logger s_logger = Logger.getLogger(ApiAsyncJobDispatcher.class);

    @Inject
    private ApiDispatcher _dispatcher;

    @Inject
    private AsyncJobManager _asyncJobMgr;
    @Inject
    private EntityManager _entityMgr;

    public ApiAsyncJobDispatcher() {
    }

    @Override
    public void runJob(final AsyncJob job) {
        BaseAsyncCmd cmdObj = null;
        try {
            Class<?> cmdClass = Class.forName(job.getCmd());
            cmdObj = (BaseAsyncCmd)cmdClass.newInstance();
            cmdObj = ComponentContext.inject(cmdObj);
            cmdObj.configure();
            cmdObj.setJob(job);

            Type mapType = new TypeToken<Map<String, String>>() {
            }.getType();
            Gson gson = ApiGsonHelper.getBuilder().create();
            Map<String, String> params = gson.fromJson(job.getCmdInfo(), mapType);

            // whenever we deserialize, the UserContext needs to be updated
            String userIdStr = params.get("ctxUserId");
            String acctIdStr = params.get("ctxAccountId");
            String contextDetails = params.get("ctxDetails");

            Long userId = null;
            Account accountObject = null;

            if (cmdObj instanceof BaseAsyncCreateCmd) {
                BaseAsyncCreateCmd create = (BaseAsyncCreateCmd)cmdObj;
                create.setEntityId(Long.parseLong(params.get("id")));
                create.setEntityUuid(params.get("uuid"));
            }

            User user = null;
            if (userIdStr != null) {
                userId = Long.parseLong(userIdStr);
                user = _entityMgr.findById(User.class, userId);
            }

            if (acctIdStr != null) {
                accountObject = _entityMgr.findById(Account.class, Long.parseLong(acctIdStr));
            }

            CallContext ctx = CallContext.register(user, accountObject);
            if(contextDetails != null){
                Type objectMapType = new TypeToken<Map<Object, Object>>() {}.getType();
                ctx.putContextParameters((Map<Object, Object>) gson.fromJson(contextDetails, objectMapType));
            }

            try {
                // dispatch could ultimately queue the job
                _dispatcher.dispatch(cmdObj, params, true);

                // serialize this to the async job table
                _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.SUCCEEDED, 0, ApiSerializerHelper.toSerializedString(cmdObj.getResponseObject()));
            } catch (InvalidParameterValueException ipve) {
                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ipve.getMessage());
            } finally {
                CallContext.unregister();
            }
        } catch (Throwable e) {
            String errorMsg = null;
            int errorCode = ApiErrorCode.INTERNAL_ERROR.getHttpCode();
            if (!(e instanceof ServerApiException)) {
                s_logger.error("Unexpected exception while executing " + job.getCmd(), e);
                errorMsg = e.getMessage();
            } else {
                ServerApiException sApiEx = (ServerApiException)e;
                errorMsg = sApiEx.getDescription();
                errorCode = sApiEx.getErrorCode().getHttpCode();
            }

            ExceptionResponse response = new ExceptionResponse();
            response.setErrorCode(errorCode);
            response.setErrorText(errorMsg);
            response.setResponseName((cmdObj == null) ? "unknowncommandresponse" : cmdObj.getCommandName());

            // FIXME:  setting resultCode to ApiErrorCode.INTERNAL_ERROR is not right, usually executors have their exception handling
            //         and we need to preserve that as much as possible here
            _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, ApiErrorCode.INTERNAL_ERROR.getHttpCode(), ApiSerializerHelper.toSerializedString(response));
        }
    }
}
