/*
* Copyright (C) 2012 The Android Open Source Project
*
* 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.
*/
package com.motorola.studio.android.emulator.logic;

import static com.motorola.studio.android.common.log.StudioLogger.debug;
import static com.motorola.studio.android.common.log.StudioLogger.error;
import static com.motorola.studio.android.common.log.StudioLogger.info;
import static com.motorola.studio.android.common.log.StudioLogger.warn;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.sequoyah.vnc.protocol.PluginProtocolActionDelegate;
import org.eclipse.sequoyah.vnc.protocol.lib.IProtocolExceptionHandler;
import org.eclipse.sequoyah.vnc.protocol.lib.ProtocolHandle;
import org.eclipse.sequoyah.vnc.protocol.lib.exceptions.InvalidDefinitionException;
import org.eclipse.sequoyah.vnc.protocol.lib.exceptions.InvalidInputStreamDataException;
import org.eclipse.sequoyah.vnc.protocol.lib.exceptions.InvalidMessageException;
import org.eclipse.sequoyah.vnc.protocol.lib.exceptions.MessageHandleException;
import org.eclipse.sequoyah.vnc.protocol.lib.exceptions.ProtocolHandshakeException;
import org.eclipse.sequoyah.vnc.protocol.lib.exceptions.ProtocolRawHandlingException;

import com.motorola.studio.android.adt.ISerialNumbered;
import com.motorola.studio.android.common.utilities.EclipseUtils;
import com.motorola.studio.android.emulator.core.exception.InstanceNotFoundException;
import com.motorola.studio.android.emulator.core.exception.InstanceStopException;
import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance;
import com.motorola.studio.android.emulator.core.utils.EmulatorCoreUtils;
import com.motorola.studio.android.emulator.i18n.EmulatorNLS;
import com.motorola.studio.android.emulator.logic.AbstractStartAndroidEmulatorLogic.LogicMode;

/**
 * DESCRIPTION:
 * Class that defines how to handle internal protocol exceptions
 * 
 * RESPONSABILITY:
 * Handle internal protocol exceptions
 * 
 * COLABORATORS:
 * None.
 * 
 * USAGE:
 * This class shall be used by Eclipse only
 */
public class AndroidExceptionHandler implements IProtocolExceptionHandler
{
    private int handlingLevel = 1;

    private boolean checkThreadRunning = false;

    private Lock lock = new ReentrantReadWriteLock().writeLock();

    private static Collection<String> stoppedWithFailure = new HashSet<String>();

    static
    {

        IJobManager manager = Job.getJobManager();
        manager.addJobChangeListener(new JobChangeAdapter()
        {
            @Override
            public void done(IJobChangeEvent event)
            {
                Job job = event.getJob();
                if (job.belongsTo(StartVncServerLogic.VNC_SERVER_JOB_FAMILY))
                {
                    IStatus result = event.getResult();
                    if (!result.isOK() && !(result.getSeverity() == IStatus.CANCEL))
                    {
                        stoppedWithFailure.add(job.getName());
                    }
                }
            }

            @Override
            public void scheduled(IJobChangeEvent event)
            {
                Job job = event.getJob();
                if (job.belongsTo(StartVncServerLogic.VNC_SERVER_JOB_FAMILY))
                {
                    stoppedWithFailure.remove(job.getName());
                }
            }
        });
    }

    /**
     * Handles internal IOExceptions caught by the protocol plugin during its execution.
     *  
     * @see IProtocolExceptionHandler#handleIOException(ProtocolHandle, IOException) 
     */
    public void handleIOException(ProtocolHandle handle, IOException e)
    {
        error("A socket was broken while communicating to server. Cause: " + e.getMessage());
        handleException(handle);
    }

    /**
     * Handles exceptions thrown by the protocol plugin when it detects an invalid message
     * definition provided by the plugin which is extending it (in this case, the core plugin).
     *  
     * @see IProtocolExceptionHandler#handleInvalidDefinitionException(ProtocolHandle, InvalidDefinitionException) 
     */
    public void handleInvalidDefinitionException(ProtocolHandle handle, InvalidDefinitionException e)
    {
        // This exception should not happen, because the message definitions are provided
        // by the development team.
        warn("An invalid message definition was detected. Cause: " + e.getMessage());
        handleException(handle);
    }

    /**
     * Handles exceptions thrown by the protocol plugin when it detects that the data retrieved from
     * the connection does not match the format defined in the message definition.
     *  
     * @see IProtocolExceptionHandler#handleInvalidInputStreamDataException(ProtocolHandle, InvalidInputStreamDataException) 
     */
    public void handleInvalidInputStreamDataException(ProtocolHandle handle,
            InvalidInputStreamDataException e)
    {
        // If the data retrieved from the connection is not as expected (considering 
        // the message definition provided), there is a high chance of errors to happen.
        // It is likely that the data from stream is no longer synchronized, so the
        // exception handling for this case is to restart connection.

        error("Some received data is not compatible with the expected definition. Restarting the protocol for synchronization.");
        handleException(handle);
    }

    /**
     * Handles exceptions thrown by the protocol plugin when it detects that the message
     * provided for sending does not have enough or valid information, given a corresponding
     * message definition
     *  
     * @see IProtocolExceptionHandler#handleInvalidMessageException(ProtocolHandle, InvalidMessageException) 
     */
    public void handleInvalidMessageException(ProtocolHandle handle, InvalidMessageException e)
    {
        // This exception should not happen, because the message object data is provided
        // by the development team. Log only.
        warn("A message was not constructed according to its definition. Cause: " + e.getMessage());
        handleException(handle);
    }

    /**
     * Handles exceptions thrown by any message handler when they discovers that it
     * is not possible to handle the message and it is a fatal error for the protocol. 
     *  
     * @see IProtocolExceptionHandler#handleMessageHandleException(ProtocolHandle, MessageHandleException) 
     */
    public void handleMessageHandleException(ProtocolHandle handle, MessageHandleException e)
    {
        // If a message handler throws a MessageHandleException, that means that it cannot
        // continue. Restart the protocol to guarantee the synchronization.
        error("A message handler has ended in error and has thrown an exception meaning the protocol cannot continue.");
        handleException(handle);
    }

    /**
     * Handles exceptions thrown by the protocol plugin when it is not possible to
     * init the protocol, for example because the handshaking procedure has failed. 
     *  
     * @see IProtocolExceptionHandler#handleProtocolHandshakeException(ProtocolHandle, ProtocolHandshakeException) 
     */
    public void handleProtocolHandshakeException(ProtocolHandle handle, ProtocolHandshakeException e)
    {
        error("Could not initialize the protocol.");
        handleException(handle);
    }

    /**
     * Handles exceptions thrown by any raw field handler when they discovers that it
     * is not possible to handle the field and it is a fatal error for the protocol. 
     *  
     * @see IProtocolExceptionHandler#handleProtocolRawHandlingException(ProtocolHandle, ProtocolRawHandlingException) 
     */
    public void handleProtocolRawHandlingException(ProtocolHandle handle,
            ProtocolRawHandlingException e)
    {
        // This message should be thrown by raw field handlers when they cannot handle the 
        // raw field and need to abort the protocol execution. Restart the protocol to 
        // guarantee the synchronization.
        error("A raw field handler has ended in error and has thrown an exception meaning the protocol cannot continue.");
        handleException(handle);
    }

    /**
     * This method will be called whenever an exception happens. It is important to find
     * out if the failure happened during an start or restart procedure, so that we can
     * do appropriate handling to each situation. 
     * 
     * @param handle The object that identifies the protocol instance
     */
    private void handleException(ProtocolHandle handle)
    {
        IAndroidEmulatorInstance instance = null;
        if (lock.tryLock())
        {
            try
            {
                instance = EmulatorCoreUtils.getAndroidInstanceByHandle(handle);

                try
                {
                    debug("Check if device is online: " + instance);
                    if (instance instanceof ISerialNumbered)
                    {
                        String serialNumber = ((ISerialNumbered) instance).getSerialNumber();
                        AndroidLogicUtils.testDeviceStatus(serialNumber);
                    }
                }
                catch (Exception e)
                {
                    error("Device is not online. Abort VNC session...");
                    abort(instance);
                }

                if ((handlingLevel == 3) && canRestartServer(instance))
                {
                    handlingLevel--;
                }

                // Firstly, try to restart only the VNC client. If restarting the VNC client 
                // is not possible, try to restart the VNC server at the device and to connect
                // to it again. If the start logic cannot be retrieved, delegate the decision 
                // to the user. 

                if (handlingLevel == 1)
                {
                    restartClientOnly(handle);
                    handlingLevel++;
                }
                else if (handlingLevel == 2)
                {
                    restartServerAndClient(instance, handle);
                    handlingLevel++;
                }
                else
                {
                    if (delegateDecisionToUser(handle))
                    {
                        abort(instance);
                    }
                }
            }
            catch (InstanceNotFoundException e)
            {
                // If the instance is not found, it means that the instance is stopped.
                // In this case, a restart is not applicable.
            }
            finally
            {
                lock.unlock();
            }
        }
    }

    private boolean canRestartServer(IAndroidEmulatorInstance instance)
    {
        String name = StartVncServerLogic.VNC_SERVER_JOB_PREFIX + instance.getName();
        return !stoppedWithFailure.contains(name);
    }

    private void restartClientOnly(final ProtocolHandle handle)
    {
        PluginProtocolActionDelegate.requestRestartProtocol(handle);

        if (!checkThreadRunning)
        {
            Runnable r = new Runnable()
            {
                public void run()
                {
                    checkThreadRunning = true;
                    while (checkThreadRunning)
                    {
                        if (PluginProtocolActionDelegate.isProtocolRunning(handle))
                        {
                            handlingLevel = 1;
                            checkThreadRunning = false;
                        }

                        try
                        {
                            Thread.sleep(500);
                        }
                        catch (InterruptedException e)
                        {
                            // Do nothing.
                        }
                    }
                }
            };
            (new Thread(r)).start();
        }
    }

    private void restartServerAndClient(IAndroidEmulatorInstance instance, ProtocolHandle handle)
    {
        try
        {
            if (instance instanceof IAndroidLogicInstance)
            {
                IAndroidLogicInstance logicInstance = (IAndroidLogicInstance) instance;
                AbstractStartAndroidEmulatorLogic logic = logicInstance.getStartLogic();
                logic.execute(logicInstance, LogicMode.TRANSFER_AND_CONNECT_VNC, logicInstance
                        .getTimeout(), new NullProgressMonitor());
                try
                {
                    Thread.sleep(1500);
                }
                catch (InterruptedException e)
                {
                    // Do nothing.
                }
                PluginProtocolActionDelegate.requestRestartProtocol(handle);
            }
            else
            {
                handlingLevel = 3;
            }
        }
        catch (Exception e1)
        {
            handlingLevel = 3;
        }
    }

    /**
     * In this method, the user is asked whether to retry or not. While the user does not
     * give up, the instance retries to connect to the emulator. When the user gives up,
     * the instance is stopped.
     * 
     * @param handle The object that identifies the protocol instance
     */
    private boolean delegateDecisionToUser(ProtocolHandle handle)
    {
        boolean abort = true;
        error("Cannot reconnect to VM. Asking to the user if he/she wants to retry.");
        if (EclipseUtils.showQuestionDialog(EmulatorNLS.GEN_Question,
                EmulatorNLS.QUESTION_AndroidExceptionHandler_ImpossibleToReconnect))
        {
            info("User chose to retry to reconnect to emulator VNC server.");
            PluginProtocolActionDelegate.requestRestartProtocol(handle);
            handlingLevel = 2;
            abort = false;
        }
        return abort;
    }

    /**
     *
     */
    private void abort(IAndroidEmulatorInstance instance)
    {
        info("User chose to stop the instance.");
        try
        {
            checkThreadRunning = false;
            instance.stop(true);
        }
        catch (InstanceStopException e1)
        {
            error("Error while running service for stopping virtual machine");
            EclipseUtils.showErrorDialog(EmulatorNLS.GEN_Error,
                    EmulatorNLS.EXC_AndroidExceptionHandler_CannotRunStopService);
        }
    }

}
