// 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.vm;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.google.gson.Gson;

import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
import org.apache.cloudstack.jobs.JobInfo;

import com.cloud.serializer.GsonHelper;
import com.cloud.utils.Pair;

/**
 * VmWorkJobHandlerProxy can not be used as standalone due to run-time
 * reflection usage in its implementation, run-time reflection conflicts with Spring proxy mode.
 * It means that we can not instantiate VmWorkJobHandlerProxy beans directly in Spring and expect
 * it can handle VmWork directly from there.
 *
 */
public class VmWorkJobHandlerProxy implements VmWorkJobHandler {

    private static final Logger s_logger = Logger.getLogger(VmWorkJobHandlerProxy.class);

    private Object _target;
    private Map<Class<?>, Method> _handlerMethodMap = new HashMap<Class<?>, Method>();

    private Gson _gsonLogger;

    public VmWorkJobHandlerProxy(Object target) {
        _gsonLogger = GsonHelper.getGsonLogger();

        buildLookupMap(target.getClass());
        _target = target;
    }

    private void buildLookupMap(Class<?> hostClass) {
        Class<?> clz = hostClass;
        while (clz != null && clz != Object.class) {
            Method[] hostHandlerMethods = clz.getDeclaredMethods();

            for (Method method : hostHandlerMethods) {
                if (isVmWorkJobHandlerMethod(method)) {
                    Class<?> paramType = method.getParameterTypes()[0];
                    assert (_handlerMethodMap.get(paramType) == null);

                    method.setAccessible(true);
                    _handlerMethodMap.put(paramType, method);
                }
            }

            clz = clz.getSuperclass();
        }
    }

    @SuppressWarnings("deprecation")
    private boolean isVmWorkJobHandlerMethod(Method method) {
        if (method.getParameterTypes().length != 1)
            return false;

        Class<?> returnType = method.getReturnType();
        if (!Pair.class.isAssignableFrom(returnType))
            return false;

        Class<?> paramType = method.getParameterTypes()[0];
        if (!VmWork.class.isAssignableFrom(paramType))
            return false;

        return true;
    }

    private Method getHandlerMethod(Class<?> paramType) {
        return _handlerMethodMap.get(paramType);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Pair<JobInfo.Status, String> handleVmWorkJob(VmWork work) throws Exception {

        Method method = getHandlerMethod(work.getClass());
        if (method != null) {

            try {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Execute VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));

                Object obj = method.invoke(_target, work);

                if (s_logger.isDebugEnabled())
                    s_logger.debug("Done executing VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));

                assert (obj instanceof Pair);
                return (Pair<JobInfo.Status, String>)obj;
            } catch (InvocationTargetException e) {
                s_logger.error("Invocation exception, caused by: " + e.getCause());

                // legacy CloudStack code relies on checked exception for error handling
                // we need to re-throw the real exception here
                if (e.getCause() != null && e.getCause() instanceof Exception) {
                    s_logger.info("Rethrow exception " + e.getCause());
                    throw (Exception)e.getCause();
                }

                throw e;
            }
        } else {
            s_logger.error("Unable to find handler for VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));

            RuntimeException ex = new RuntimeException("Unable to find handler for VM work job: " + work.getClass().getName());
            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, JobSerializerHelper.toObjectSerializedString(ex));
        }
    }
}
