class CheckConsistencyCommand implements AdminCommand {

    @Override
    public void execute( String[] args ) throws IncorrectUsage, CommandFailed
    {
        final String database;
        final boolean verbose;
        final Optional<Path> additionalConfigFile;
        final Path reportDir;
        final Optional<Path> backupPath;
        final boolean checkGraph;
        final boolean checkIndexes;
        final boolean checkIndexStructure;
        final boolean checkLabelScanStore;
        final boolean checkPropertyOwners;

        try
        {
            database = arguments.parse( args ).get( ARG_DATABASE );
            backupPath = arguments.getOptionalPath( "backup" );
            verbose = arguments.getBoolean( "verbose" );
            additionalConfigFile = arguments.getOptionalPath( "additional-config" );
            reportDir = arguments.getOptionalPath( "report-dir" )
                    .orElseThrow( () -> new IllegalArgumentException( "report-dir must be a valid path" ) );
        }
        catch ( IllegalArgumentException e )
        {
            throw new IncorrectUsage( e.getMessage() );
        }

        if ( backupPath.isPresent() )
        {
            if ( arguments.has( ARG_DATABASE ) )
            {
                throw new IncorrectUsage( "Only one of '--" + ARG_DATABASE + "' and '--backup' can be specified." );
            }
            if ( !backupPath.get().toFile().isDirectory() )
            {
                throw new CommandFailed( format( "Specified backup should be a directory: %s", backupPath.get() ) );
            }
        }

        Config config = loadNeo4jConfig( homeDir, configDir, database, loadAdditionalConfig( additionalConfigFile ) );

        try
        {
            // We can remove the loading from config file in 4.0
            if ( arguments.has( CHECK_GRAPH ) )
            {
                checkGraph = arguments.getBoolean( CHECK_GRAPH );
            }
            else
            {
                checkGraph = config.get( ConsistencyCheckSettings.consistency_check_graph );
            }
            if ( arguments.has( CHECK_INDEXES ) )
            {
                checkIndexes = arguments.getBoolean( CHECK_INDEXES );
            }
            else
            {
                checkIndexes = config.get( ConsistencyCheckSettings.consistency_check_indexes );
            }
            if ( arguments.has( CHECK_INDEX_STRUCTURE ) )
            {
                checkIndexStructure = arguments.getBoolean( CHECK_INDEX_STRUCTURE );
            }
            else
            {
                checkIndexStructure = config.get( ConsistencyCheckSettings.consistency_check_index_structure );
            }
            if ( arguments.has( CHECK_LABEL_SCAN_STORE ) )
            {
                checkLabelScanStore = arguments.getBoolean( CHECK_LABEL_SCAN_STORE );
            }
            else
            {
                checkLabelScanStore = config.get( ConsistencyCheckSettings.consistency_check_label_scan_store );
            }
            if ( arguments.has( CHECK_PROPERTY_OWNERS ) )
            {
                checkPropertyOwners = arguments.getBoolean( CHECK_PROPERTY_OWNERS );
            }
            else
            {
                checkPropertyOwners = config.get( ConsistencyCheckSettings.consistency_check_property_owners );
            }
        }
        catch ( IllegalArgumentException e )
        {
            throw new IncorrectUsage( e.getMessage() );
        }

        try ( FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction() )
        {
            File databaseDirectory = backupPath.map( Path::toFile ).orElse( config.get( database_path ) );
            DatabaseLayout databaseLayout = DatabaseLayout.of( databaseDirectory );
            checkDbState( databaseLayout, config );
            ZoneId logTimeZone = config.get( GraphDatabaseSettings.db_timezone ).getZoneId();
            // Only output progress indicator if a console receives the output
            ProgressMonitorFactory progressMonitorFactory = ProgressMonitorFactory.NONE;
            if ( System.console() != null )
            {
                progressMonitorFactory = ProgressMonitorFactory.textual( System.out );
            }

            ConsistencyCheckService.Result consistencyCheckResult = consistencyCheckService
                    .runFullConsistencyCheck( databaseLayout, config, progressMonitorFactory,
                            FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( System.out ), fileSystem,
                            verbose, reportDir.toFile(),
                            new ConsistencyFlags( checkGraph, checkIndexes, checkIndexStructure, checkLabelScanStore, checkPropertyOwners ) );

            if ( !consistencyCheckResult.isSuccessful() )
            {
                throw new CommandFailed( format( "Inconsistencies found. See '%s' for details.",
                        consistencyCheckResult.reportFile() ) );
            }
        }
        catch ( ConsistencyCheckIncompleteException | IOException e )
        {
            throw new CommandFailed( "Consistency checking failed." + e.getMessage(), e );
        }
    }

    public  CheckConsistencyCommand( Path homeDir, Path configDir );
    public  CheckConsistencyCommand( Path homeDir, Path configDir, ConsistencyCheckService consistencyCheckService );

}