class ShardService {

    public CompletableFuture<MigrateState> tryCreateShardAsync(int lastTrimBlockHeight, int blockchainHeight) {
        CompletableFuture<MigrateState> newShardingProcess = null;
        log.debug(">> tryCreateShardAsync, scanning ? = {}, !isSharding={},\nCurrent config = {}",
            !blockchainProcessor.isScanning(), !isSharding, blockchainConfig.getCurrentConfig());
        if (!blockchainProcessor.isScanning()) {
            if (!isSharding) {
                Shard lastShard = shardDao.getLastShard();
                if (lastShard == null || lastTrimBlockHeight > lastShard.getShardHeight()) {
                    isSharding = true;
                    updateTrimConfig(false, false);
                    // quick create records for new Shard and Recovery process for later use
                    long nextShardId = shardDao.getNextShardId();
                    log.debug("Prepare for next sharding = '{}' at height = '{}', lastTrimHeight = '{}'",
                        nextShardId, blockchainHeight, lastTrimBlockHeight);
                    saveShardRecoveryAndShard(nextShardId, lastTrimBlockHeight, blockchainHeight);

                    this.shardingProcess = CompletableFuture.supplyAsync(() -> performSharding(lastTrimBlockHeight, nextShardId, MigrateState.INIT));
                    this.shardingProcess.handle((result, ex) -> {
                        blockchain.setShardInitialBlock(blockchain.findFirstBlock());
                        updateTrimConfig(true, false);
                        isSharding = false;
                        return result;
                    });
                    newShardingProcess = this.shardingProcess;
                } else {
                    log.warn("Last trim height {} less than last shard height {}", lastTrimBlockHeight, lastShard.getShardHeight());
                }
            } else {
                log.warn("Unable to start sharding at height {}, previous sharding process was not finished", lastTrimBlockHeight);
            }
        } else {
            log.warn("Will skip sharding at height {} due to current blockchain scanning !", lastTrimBlockHeight);
        }
        return newShardingProcess;
    }

    @Inject public  ShardService(ShardDao shardDao, BlockchainProcessor blockchainProcessor, Blockchain blockchain,
                        DirProvider dirProvider, Zip zip, DatabaseManager databaseManager,
                        BlockchainConfig blockchainConfig, ShardRecoveryDao shardRecoveryDao,
                        ShardMigrationExecutor shardMigrationExecutor, AplAppStatus aplAppStatus,
                        PropertiesHolder propertiesHolder, Event<TrimConfig> trimEvent, GlobalSync globalSync,
                        TrimService trimService, Event<DbHotSwapConfig> dbEvent);

}