class TrimService {

    public void init(int height, int shardInitialBlockHeight) {
        log.debug("TRIM: init() at height = {}, shard initial height={}", height, shardInitialBlockHeight);
        lock.lock();
        try {
            TrimEntry trimEntry = trimDao.get();
            if (trimEntry == null) {
                log.info("Trim was not saved previously (existing database on new code). Skip trim");
                trimDao.save(new TrimEntry(null, height, true));
                return;
            }
            int lastTrimHeight = trimEntry.getHeight();
            log.info("Last trim height '{}' was done? ='{}', supplied height {}",
                lastTrimHeight, trimEntry.isDone(), height);
            if (lastTrimHeight < shardInitialBlockHeight) {
                //we need to change the lastTrimHeight value according to the first block in the latest shard
                lastTrimHeight = shardInitialBlockHeight;
                log.info("Set last trim height to shard initial block height={}", lastTrimHeight);
            }
            if (!trimEntry.isDone()) {
                log.info("Finish trim at height {}", lastTrimHeight);
                trimDerivedTables(lastTrimHeight, false);
            }
            //TODO: Do we really need to do so many iterations or something about two-three heights from tail would be enough?
            for (int i = lastTrimHeight + trimFrequency; i <= height; i += trimFrequency) {
                log.info("Perform trim on height {}", i);
                trimDerivedTables(i, false);
            }
        } finally {
            lock.unlock();
        }
    }

    @Inject public  TrimService(DatabaseManager databaseManager,
                       DerivedTablesRegistry derivedDbTablesRegistry,
                       GlobalSync globalSync,
                       TimeService timeService,
                       Event<TrimData> trimEvent,
                       Event<TrimConfig> trimConfigEvent,
                       TrimDao trimDao,
                       @Property(value = "apl.maxRollback", defaultValue = "720") int maxRollback
    );

}