/*
 * 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;

import org.apache.ode.bpel.bdi.breaks.ActivityBreakpoint;
import org.apache.ode.bpel.bdi.breaks.Breakpoint;
import org.apache.ode.bpel.bdi.breaks.VariableModificationBreakpoint;
import org.apache.ode.bpel.common.CorrelationKey;
import org.apache.ode.bpel.dao.*;
import org.apache.ode.bpel.iapi.BpelServer;
import org.apache.ode.bpel.iapi.ProcessStore;
import org.apache.ode.bpel.obj.OProcess;
import org.apache.ode.bpel.pmapi.*;
import org.apache.ode.bpel.pmapi.TInstanceInfo.EventInfo;
import org.apache.ode.bpel.runtime.breaks.ActivityBreakpointImpl;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.uuid.UUIDGen;
import org.w3c.dom.Node;

import javax.xml.namespace.QName;
import java.util.*;

/**
 * Implementation of the instance/process management interaction. This class implements
 * the methods necessary to support process debugging. It also implements all the methods in the
 * newer Process/Instance Management interface (pmapi).
 */
public class BpelManagementFacadeImpl extends ProcessAndInstanceManagementImpl
        implements BpelManagementFacade {
    private static UUIDGen _uuidGen = new UUIDGen();

    public BpelManagementFacadeImpl(BpelServer server, ProcessStore store) {
        super(server, store);
    }

    public short getState(final Long iid) throws ManagementException {

        return dbexec(new BpelDatabase.Callable<Short>()  {
            public Short run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                return Short.valueOf(instance.getState());
            }
        }).shortValue();

    }


    public Long getProcessInstance(String pid, final CorrelationKey ckey) throws ManagementException {

        return dbexec(_db.getProcessDb(QName.valueOf(pid)).new Callable<Long>()  {
            public Long run(BpelDAOConnection session) throws Exception {
                Iterator<ProcessInstanceDAO> i = getProcessDAO().findInstance(ckey).iterator();
                return (i.hasNext()) ? i.next().getInstanceId() : null;
            }
        });
    }

    public EventInfoListDocument getEvents(final Long iid, final int startIdx, final int count)
            throws ManagementException {

        // TODO: this is a bit of hack, if there are two events with exactly the
        // same timestamp, we can have more events returned then requested.

        List<String> timeline;

        try {
            timeline = getEventTimeline("iid="+iid,null);
        } catch (Exception ex) {
            throw new ManagementException("Unable to retrieve timeline.", ex);
        }

        if (startIdx >= timeline.size())
            return EventInfoListDocument.Factory.newInstance();

        timeline = timeline.subList(startIdx,Math.min(timeline.size(),startIdx+count));
        String startdt = timeline.get(0);
        String enddt = timeline.get(timeline.size()-1);

        return listEvents("iid="+iid,"timestamp>="+startdt +" " +"timestamp<="+enddt,0);
    }

    public int getEventCount(final Long iid) throws ManagementException {
        EventInfo einfo = getInstanceInfo(iid).getInstanceInfo().getEventInfo();
        if (einfo == null)
            return 0;
        return einfo.getCount();
    }



    public String getVariable(final Long iid, final Long scopeId, final String varName)
            throws ManagementException {
        return dbexec(new BpelDatabase.Callable<String>()  {
            public String run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                if (instance == null) {
                    throw new ManagementException("InstanceNotFound:" + iid);
                }
                ScopeDAO scope = instance.getScope(scopeId);
                if (scope == null) {
                    throw new ManagementException("ScopeNotFound:" + scopeId);
                }
                XmlDataDAO var = scope.getVariable(varName);
                if (var == null) {
                    throw new ManagementException("VarNotFound:" + varName);
                }
                return nodeToString(var);
            }
        });
    }

    public Long[] getScopeInstancesForScope(final Long iid, final String scopeName) throws ManagementException {

        return dbexec(new BpelDatabase.Callable<Long[]>()  {
            public Long[] run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                if (instance == null) {
                    throw new ManagementException("InstanceNotFound:" + iid);
                }
                Collection<ScopeDAO> scopes = instance.getScopes(scopeName);
                List<Long>instanceIds = new ArrayList<Long>(scopes.size());
                for(ScopeDAO i : scopes) {
                    instanceIds.add(i.getScopeInstanceId());
                }
                return instanceIds.toArray(new Long[scopes.size()]);
            }
        });
    }

    public void setVariable(Long pid, Long scopeId, String varName, String data) {
        throw new UnsupportedOperationException();
    }

    public void setCorrelation(final Long iid, final Long scopeId, final String correlationSet,
                               final QName[] propertyNames, final CorrelationKey values)
            throws ManagementException {

        dbexec(new BpelDatabase.Callable<Object>()  {
            public Object run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                if (instance == null) {
                    throw new ManagementException("InstanceNotFound:" + iid);
                }
                CorrelationSetDAO correlationSetDAO = instance.getCorrelationSet(correlationSet);
                correlationSetDAO.setValue(propertyNames, values);
                return null;
            }
        });

    }

    public CorrelationKey getCorrelation(final Long iid, final Long scopeId, final String correlationSet) throws ManagementException {
        return dbexec(new BpelDatabase.Callable<CorrelationKey>()  {
            public CorrelationKey run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                if (instance == null) {
                    throw new ManagementException("InstanceNotFound:" + iid);
                }
                CorrelationSetDAO corr = findCorrelationSetDAO(instance, scopeId, correlationSet);
                return corr.getValue();
            }
        });
    }

    /**
     * @see BpelManagementFacade#getProcessDef(String)
     * @param procid
     */
    public OProcess getProcessDef(String procid) throws ManagementException {
        if (_server._engine == null)
            throw new ProcessingException("ServiceProvider required for debugger operation.");

        BpelProcess process = _server._engine._activeProcesses.get(QName.valueOf(procid));
        if (process == null)
            throw new InvalidRequestException("The process \"" + procid + "\" is not available. Please make sure it is deployed and encompassing System is activated." );

        return process.getOProcess();
    }

    public void step(final Long iid) throws ManagementException {
        // We need debugger support in order to resume (since we have to force
        // a reduction. If one is not available the getDebugger() method should
        // throw a ProcessingException
        DebuggerSupport debugSupport = getDebugger(iid);
        assert debugSupport != null : "getDebugger(Long) returned NULL!";
        debugSupport.step(iid);
    }

    public QName getCompletedFault(final Long iid) throws ManagementException {

        return dbexec(new BpelDatabase.Callable<QName>()  {
            public QName run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                if (instance == null)
                    throw new ManagementException("InstanceNotFound:" + iid);
                return instance.getFault().getName();
            }
        });
    }

    public Breakpoint[] getGlobalBreakpoints(String procId) throws ManagementException {
        DebuggerSupport debuggerSupport = getDebugger(QName.valueOf(procId));
        return debuggerSupport.getGlobalBreakpoints();
    }

    public Breakpoint[] getBreakpoints(Long iid) throws ManagementException {
        DebuggerSupport debuggerSupport = getDebugger(iid);
        return debuggerSupport.getBreakpoints(iid);
    }


    public void removeGlobalBreakpoint(String procid, Breakpoint sp) throws ManagementException {
        DebuggerSupport debuggerSupport = getDebugger(QName.valueOf(procid));
        debuggerSupport.removeGlobalBreakpoint(sp);
    }

    public void removeBreakpoint(Long iid, Breakpoint sp) throws ManagementException {
        DebuggerSupport debuggerSupport = getDebugger(iid);
        debuggerSupport.removeBreakpoint(iid, sp);
    }

    public ActivityBreakpoint addGlobalActivityBreakpoint(String procid, String activity) throws ManagementException {
        DebuggerSupport debuggerSupport = getDebugger(QName.valueOf(procid));

        ActivityBreakpointImpl bp = new ActivityBreakpointImpl(_uuidGen.nextUUID(), activity);
        debuggerSupport.addGlobalBreakpoint(bp);
        return bp;
    }

    public ActivityBreakpoint addActivityBreakpoint(Long iid, String activity) throws ManagementException {
        DebuggerSupport debuggerSupport = getDebugger(iid);

        ActivityBreakpointImpl bp = new ActivityBreakpointImpl(_uuidGen.nextUUID(), activity);
        debuggerSupport.addBreakpoint(iid, bp);
        return bp;
    }

    public VariableModificationBreakpoint addVariableModificationBreakpoint(Long iid, String scopename, String variable) {
        throw new UnsupportedOperationException();
    }

    public Date getStartTime(final Long iid) throws ManagementException {

        return dbexec(new BpelDatabase.Callable<Date>()  {
            public Date run(BpelDAOConnection session) throws Exception {
                ProcessInstanceDAO instance = session.getInstance(iid);
                if (instance == null)
                    throw new InstanceNotFoundException("InstanceNotFound:" + iid);
                return instance.getCreateTime();
            }
        });
    }

    private CorrelationSetDAO findCorrelationSetDAO(ProcessInstanceDAO instance, Long scopeId, String correlationSet)
            throws ManagementException {
        ScopeDAO scope = instance.getScope(scopeId);
        CorrelationSetDAO corr = null;
        do {
            corr = scope.getCorrelationSet(correlationSet);
            if(corr != null)
                break;
            scope = scope.getParentScope();
        } while(scope != null);

        if(corr == null)
            throw new ManagementException("CorrelationSetNotFound:" + correlationSet);

        return corr;
    }


    private static String nodeToString(XmlDataDAO xml){
        Node data = xml.get();
        String str;
        if (data == null) {
            str = null;
        } else if (data.getNodeType() == Node.ELEMENT_NODE) {
            str = DOMUtils.domToString(data);
        } else {
            str = data.getNodeValue();
        }
        return str;
    }
}
