package org.zstack.network.service.virtualrouter.ha;

import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.zstack.core.asyncbatch.While;
import org.zstack.core.componentloader.PluginRegistry;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.header.core.Completion;
import org.zstack.header.core.WhileDoneCompletion;
import org.zstack.header.core.workflow.Flow;
import org.zstack.header.core.workflow.FlowRollback;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.errorcode.ErrorCodeList;
import org.zstack.header.network.service.VirtualRouterHaGroupExtensionPoint;
import org.zstack.header.vm.VmInstanceConstant;
import org.zstack.header.vm.VmInstanceSpec;
import org.zstack.network.service.virtualrouter.VirtualRouterConstant;
import org.zstack.network.service.virtualrouter.VirtualRouterVmInventory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class VirtualRouterHaSyncConfigToBackendFlow implements Flow {
    @Autowired
    protected DatabaseFacade dbf;
    @Autowired
    protected PluginRegistry pluginRgty;

    @Override
    public void run(final FlowTrigger chain, Map data) {
        final VirtualRouterVmInventory vr = (VirtualRouterVmInventory) data.get(VirtualRouterConstant.Param.VR.toString());
        if (!vr.isHaEnabled()) {
            chain.next();
            return;
        }

        /* only when create a new vpc router, vyos ha config need to be updated to peer router */
        boolean syncPeer = false;
        VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());
        if (spec != null && spec.getCurrentVmOperation() == VmInstanceConstant.VmOperation.NewCreate) {
            syncPeer = true;
        }

        final boolean fSyncPeer = syncPeer;
        List<ErrorCode> errs = new ArrayList<>();
        List<VirtualRouterHaGroupExtensionPoint> exts = pluginRgty.getExtensionList(VirtualRouterHaGroupExtensionPoint.class);
        new While<>(exts).each((ext, compl) -> {
            ext.syncVirtualRouterHaConfigToBackend(vr.getUuid(), fSyncPeer, new Completion(compl) {
                @Override
                public void success() {
                    compl.done();
                }

                @Override
                public void fail(ErrorCode errorCode) {
                    errs.add(errorCode);
                    compl.done();
                }
            });
        }).run(new WhileDoneCompletion(chain) {
            @Override
            public void done(ErrorCodeList errorCodeList) {
                if (errs.isEmpty()) {
                    chain.next();
                } else {
                    chain.fail(errs.get(0));
                }
            }
        });
    }

    @Override
    public void rollback(FlowRollback chain, Map data) {
        chain.rollback();
    }
}

@@ -234,24 +234,75 @@
 nfigurable;%0A
+import org.zstack.appliancevm.ApplianceVmConstant;%0A
 import org.z
@@ -1698,382 +1698,85 @@
  /* 
-only when create a new vpc router, vyos ha config need to be updated to peer router */%0A        boolean syncPeer = false;%0A        VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());%0A        if (spec != null && spec.getCurrentVmOperation() == VmInstanceConstant.VmOperation.NewCreate) %7B%0A            syncPeer = true;%0A        %7D%0A
+sync config to peer all the time to make sure: both vroute has same config */
 %0A   
@@ -1794,18 +1794,17 @@
 boolean 
-fS
+s
 yncPeer 
@@ -1805,24 +1805,20 @@
 cPeer = 
-syncPeer
+true
 ;%0A      
@@ -2106,10 +2106,9 @@
 (), 
-fS
+s
 yncP

update vpcha config to peer router at same time