class ShardService {

    public boolean reset(long shardId) {

        Path dbDir = dirProvider.getDbDir();
        Path backupZip = dbDir.resolve(String.format(ShardConstants.DB_BACKUP_FORMAT, new ShardNameHelper().getShardNameByShardId(shardId, blockchainConfig.getChain().getChainId())));
        boolean backupExists = Files.exists(backupZip);
        if (backupExists) {
            if (isSharding) {
                if (shardingProcess != null) {
                    log.info("Stopping sharding process...");
                    shardingProcess.cancel(true);
                } else {
                    log.info("Unable to stop sharding process. Try again later");
                    return false;
                }
            }

            updateTrimConfig(false, true);
            blockchainProcessor.suspendBlockchainDownloading();
            try {
                log.debug("Waiting finish of last trim");
                while (trimService.isTrimming()) {
                    ThreadUtils.sleep(100);
                }
                globalSync.writeLock();
                try {

                    databaseManager.setAvailable(false);
                    dbEvent.fire(new DbHotSwapConfig(shardId));
                    databaseManager.shutdown();
                    FileUtils.deleteFilesByFilter(dirProvider.getDbDir(), (p) -> {
                        Path fileName = p.getFileName();
                        int shardIndex = fileName.toString().indexOf("-shard-");
                        if ((fileName.toString().endsWith(DbProperties.DB_EXTENSION) || fileName.toString().endsWith("trace.db"))
                            && shardIndex != -1) {
                            String idString = fileName.toString().substring(shardIndex + 7);
                            String id = idString.substring(0, idString.indexOf("-"));
                            long fileShardId = Long.parseLong(id);
                            return fileShardId >= shardId;
                        } else {
                            return false;
                        }
                    });
                    zip.extract(backupZip.toAbsolutePath().toString(), dbDir.toAbsolutePath().toString(), true);
                    databaseManager.setAvailable(true);
                    databaseManager.getDataSource(); // force init
                    blockchain.update();
                    recoverSharding();
                    return true;
                } finally {
                    globalSync.writeUnlock();
                }
            } finally {
                blockchainProcessor.resumeBlockchainDownloading();
                updateTrimConfig(true, false);
            }
        } else {
            log.debug("Backup before shard {} does not exist", shardId);
            return false;
        }
    }

    @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);

}