/*
 * 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 org.apache.ode.bpel.engine.migration;

import org.apache.ode.bpel.engine.BpelProcess;
import org.apache.ode.bpel.engine.OutstandingRequestManager;
import org.apache.ode.bpel.engine.ReplacementMapImpl;
import org.apache.ode.bpel.dao.BpelDAOConnection;
import org.apache.ode.bpel.dao.ProcessInstanceDAO;
import org.apache.ode.bpel.dao.ProcessDAO;
import org.apache.ode.bpel.runtime.Selector;
import org.apache.ode.bpel.common.CorrelationKey;
import org.apache.ode.bpel.common.CorrelationKeySet;
import org.apache.ode.bpel.obj.OProcess;
import org.apache.ode.jacob.vpu.ExecutionQueueImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.namespace.QName;
import java.util.Set;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.io.ObjectStreamClass;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * Migrates the database from using single correlations to multiple correlations support.
 */
public class CorrelationKeySetMigration implements Migration {
    private static final Logger __log = LoggerFactory.getLogger(CorrelationKeySetMigration.class);

    public boolean migrate(Set<BpelProcess> registeredProcesses, BpelDAOConnection connection) {
        boolean v1First = true;
        for (BpelProcess process : registeredProcesses) {
            ProcessDAO processDao = connection.getProcess(process.getConf().getProcessId());
            Collection<ProcessInstanceDAO> pis = processDao.getActiveInstances();

            // Migrate the correlation key stored in the jacob state of the instance
            for (ProcessInstanceDAO instance : pis) {
                __log.debug("Migrating correlation key in jacob for instance " + instance.getInstanceId());
                OProcess oproc = findOProcess(registeredProcesses, instance.getProcess().getProcessId());
                if (v1First) {
                    if (!updateV1Key(instance, oproc)) {
                        v1First = false;
                        updateV2Key(instance, oproc);
                    }
                } else {
                    if (!updateV2Key(instance, oproc)) {
                        v1First = true;
                        updateV1Key(instance, oproc);
                    }
                }
            }
        }

        return true;
    }

    private boolean updateV1Key(ProcessInstanceDAO instance, OProcess oproc) {
        ExecutionQueueImpl soup;
        try {
            soup = readOldState(instance, oproc, getClass().getClassLoader(), true);
            if (soup == null) return false;
        } catch (Exception e) {
            __log.debug("  failed to read a v1 state for instance " + instance.getInstanceId());
            ExecutionQueueImpl._classDescriptors.clear();
            return false;
        }
        try {
            OutstandingRequestManager orm = (OutstandingRequestManager) soup.getGlobalData();
            for (OutstandingRequestManager.Entry entry : orm._byChannel.values()) {
                Selector[] newSelectors = new Selector[entry.selectors.length];
                int index = 0;
                for (Object selector : entry.selectors) {
                    OldSelector sel = (OldSelector)selector;
                    Object selCKey = sel.correlationKey;
                    if (selCKey != null) {
                        OldCorrelationKey old = (OldCorrelationKey) selCKey;
                        __log.debug("   Changing V1 key " + old.toCanonicalString());

                        CorrelationKeySet newKeySet = new CorrelationKeySet();
                        newKeySet.add(new CorrelationKey(""+old.getCSetId(), old.getValues()));
                        Selector newSelector = new Selector(sel.idx, sel.plinkInstance, sel.opName,
                                sel.oneWay, sel.messageExchangeId, newKeySet, "one");
                        newSelector.correlationKey = new CorrelationKey(""+old.getCSetId(), old.getValues());
                        newSelectors[index++] = newSelector;
                    }
                }
                entry.selectors = newSelectors;
            }

            writeOldState(instance, soup);
        } finally {
            ExecutionQueueImpl._classDescriptors.clear();
        }
        return true;
    }

    private boolean updateV2Key(ProcessInstanceDAO instance, OProcess oproc) {
        ExecutionQueueImpl soup;
        try {
            soup = readOldState(instance, oproc, getClass().getClassLoader(), false);
            if (soup == null) return false;
        } catch (Exception e) {
            __log.debug("  failed to read a v2 state for instance " + instance.getInstanceId());
            ExecutionQueueImpl._classDescriptors.clear();
            return false;
        }
        OutstandingRequestManager orm = (OutstandingRequestManager) soup.getGlobalData();
        for (OutstandingRequestManager.Entry entry : orm._byChannel.values()) {
            Selector[] newSelectors = new Selector[entry.selectors.length];
            int index = 0;
            for (Object selector : entry.selectors) {
                OldSelector sel = (OldSelector)selector;
                CorrelationKey selCKey = (CorrelationKey) sel.correlationKey;
                if (selCKey != null) {
                    __log.debug("   Changing V2 key " + selCKey.toCanonicalString());

                    CorrelationKeySet newKeySet = new CorrelationKeySet();
                    newKeySet.add(new CorrelationKey(""+selCKey.getCorrelationSetName(), selCKey.getValues()));
                    Selector newSelector = new Selector(sel.idx, sel.plinkInstance, sel.opName,
                            sel.oneWay, sel.messageExchangeId, newKeySet, "one");
                    newSelector.correlationKey = new CorrelationKey(""+selCKey.getCorrelationSetName(), selCKey.getValues());
                    newSelectors[index++] = newSelector;
                }
            }
            entry.selectors = newSelectors;
        }

        writeOldState(instance, soup);
        return true;
    }

    private ExecutionQueueImpl readOldState(ProcessInstanceDAO instance, OProcess oprocess,
                                            ClassLoader cl, boolean changeKey) {
        if (instance.getExecutionState() == null) return null;
        try {
            ExecutionQueueImpl soup = new ExecutionQueueImpl(cl);
            ObjectStreamClass osc;
            if (changeKey) {
                osc = ObjectStreamClass.lookup(Class.forName(
                        "org.apache.ode.bpel.engine.migration.OldCorrelationKey", true, cl));
                ExecutionQueueImpl._classDescriptors.put("org.apache.ode.bpel.common.CorrelationKey", osc);
            }
            osc = ObjectStreamClass.lookup(Class.forName(
                    "org.apache.ode.bpel.engine.migration.OldSelector", true, cl));
            ExecutionQueueImpl._classDescriptors.put("org.apache.ode.bpel.runtime.Selector", osc);
            osc = ObjectStreamClass.lookup(Class.forName(
                    "[Lorg.apache.ode.bpel.engine.migration.OldSelector;", true, getClass().getClassLoader()));
            ExecutionQueueImpl._classDescriptors.put("[Lorg.apache.ode.bpel.runtime.Selector;", osc);

            soup.setReplacementMap(new ReplacementMapImpl(oprocess));
            ByteArrayInputStream iis = new ByteArrayInputStream(instance.getExecutionState());
            soup.read(iis);
            return soup;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void writeOldState(ProcessInstanceDAO instance, ExecutionQueueImpl soup) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            soup.write(bos);
            bos.close();
            instance.setExecutionState(bos.toByteArray());
            ExecutionQueueImpl._classDescriptors.clear();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private OProcess findOProcess(Set<BpelProcess> registeredProcesses, QName name) {
        for (BpelProcess process : registeredProcesses) {
            if (process.getConf().getProcessId().equals(name)) return process.getOProcess();
        }
        return null;
    }

}
