/*
 * This file is part of Bisq.
 *
 * Bisq is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 *
 * Bisq is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Bisq. If not, see <http://www.gnu.org/licenses/>.
 */

package bisq.core.dao;

import bisq.core.dao.governance.asset.AssetService;
import bisq.core.dao.governance.ballot.BallotListService;
import bisq.core.dao.governance.blindvote.BlindVoteListService;
import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository;
import bisq.core.dao.governance.bond.reputation.MyReputationListService;
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
import bisq.core.dao.governance.period.CycleService;
import bisq.core.dao.governance.proofofburn.ProofOfBurnService;
import bisq.core.dao.governance.proposal.ProposalService;
import bisq.core.dao.governance.voteresult.MissingDataRequestService;
import bisq.core.dao.governance.voteresult.VoteResultService;
import bisq.core.dao.governance.votereveal.VoteRevealService;
import bisq.core.dao.node.BsqNode;
import bisq.core.dao.node.BsqNodeProvider;
import bisq.core.dao.node.explorer.ExportJsonFilesService;
import bisq.core.dao.state.DaoStateService;

import com.google.inject.Inject;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * High level entry point for Dao domain.
 * We initialize all main service classes here to be sure they are started.
 */
public class DaoSetup {
    private final BsqNode bsqNode;
    private final List<DaoSetupService> daoSetupServices = new ArrayList<>();

    @Inject
    public DaoSetup(BsqNodeProvider bsqNodeProvider,
                    DaoStateService daoStateService,
                    CycleService cycleService,
                    ProposalService proposalService,
                    BallotListService ballotListService,
                    BlindVoteListService blindVoteListService,
                    MyBlindVoteListService myBlindVoteListService,
                    VoteRevealService voteRevealService,
                    VoteResultService voteResultService,
                    MissingDataRequestService missingDataRequestService,
                    BondedReputationRepository bondedReputationRepository,
                    BondedRolesRepository bondedRolesRepository,
                    MyReputationListService myReputationListService,
                    MyBondedReputationRepository myBondedReputationRepository,
                    AssetService assetService,
                    ProofOfBurnService proofOfBurnService,
                    DaoFacade daoFacade,
                    ExportJsonFilesService exportJsonFilesService) {

        bsqNode = bsqNodeProvider.getBsqNode();

        // We need to take care of order of execution.
        daoSetupServices.add(daoStateService);
        daoSetupServices.add(cycleService);
        daoSetupServices.add(proposalService);
        daoSetupServices.add(ballotListService);
        daoSetupServices.add(blindVoteListService);
        daoSetupServices.add(myBlindVoteListService);
        daoSetupServices.add(voteRevealService);
        daoSetupServices.add(voteResultService);
        daoSetupServices.add(missingDataRequestService);
        daoSetupServices.add(bondedReputationRepository);
        daoSetupServices.add(bondedRolesRepository);
        daoSetupServices.add(myReputationListService);
        daoSetupServices.add(myBondedReputationRepository);
        daoSetupServices.add(assetService);
        daoSetupServices.add(proofOfBurnService);
        daoSetupServices.add(daoFacade);
        daoSetupServices.add(exportJsonFilesService);
        daoSetupServices.add(bsqNodeProvider.getBsqNode());
    }

    public void onAllServicesInitialized(Consumer<String> errorMessageHandler,
                                         Consumer<String> warnMessageHandler) {
        bsqNode.setErrorMessageHandler(errorMessageHandler);
        bsqNode.setWarnMessageHandler(warnMessageHandler);

        daoSetupServices.forEach(daoSetupServices -> {
            daoSetupServices.addListeners();
            daoSetupServices.start();
        });
    }

    public void shutDown() {
        bsqNode.shutDown();
    }
}

@@ -2357,32 +2357,36 @@
     
-ProposalService proposal
+BallotListService ballotList
 Serv
@@ -2414,36 +2414,32 @@
     
-BallotListService ballotList
+ProposalService proposal
 Serv
@@ -3464,55 +3464,8 @@
 e);%0A
-        daoSetupServices.add(proposalService);%0A
     
@@ -3501,32 +3501,79 @@
 otListService);%0A
+        daoSetupServices.add(proposalService);%0A
         daoSetup
@@ -4591,84 +4591,341 @@
     
-daoSetupServices.forEach(daoSetupServices -%3E %7B%0A            daoSetupServices.
+// We add first all listeners at all services and then call the start methods.%0A        // Some services are listening on others so we need to make sure that the%0A        // listeners are set before we call start as that might trigger state change%0A        // which triggers listeners.%0A        daoSetupServices.forEach(DaoSetupService::
 addL
@@ -4932,17 +4932,16 @@
 isteners
-(
 );%0A     
@@ -4939,28 +4939,24 @@
 s);%0A        
-    
 daoSetupServ
@@ -4964,26 +4964,38 @@
 ces.
-start();%0A        %7D
+forEach(DaoSetupService::start
 );%0A 

Change handling of addListeners and start calls