func main() {
	if len(os.Args) < 2 || len(os.Args) > 3 {
		println("Usage: blt path/to/config.json [path/to/state.json]")
		os.Exit(1)
	}

	logger := boshlog.NewLogger(boshlog.LevelDebug)
	fs := boshsys.NewOsFileSystem(logger)
	cmdRunner := boshsys.NewExecCmdRunner(logger)

	config := bltconfig.NewConfig(fs)
	err := config.Load(os.Args[1])
	if err != nil {
		panic(err)
	}

	assetsProvider := bltassets.NewProvider(config.AssetsPath)

	logger.Debug("main", "Setting up environment")
	environmentProvider := bltenv.NewProvider(config, fs, cmdRunner, assetsProvider)
	environment := environmentProvider.Get()
	err = environment.Setup()
	if err != nil {
		panic(err)
	}
	defer environment.Shutdown()
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		environment.Shutdown()
		os.Exit(1)
	}()

	logger.Debug("main", "Starting deploy")

	cliRunnerFactory := bltclirunner.NewFactory(config.CliCmd, cmdRunner, fs)

	directorInfo, err := bltaction.NewDirectorInfo(environment.DirectorURL(), cliRunnerFactory)
	if err != nil {
		panic(err)
	}

	actionFactory := bltaction.NewFactory(directorInfo, fs, assetsProvider)

	prepareActionFlow := bltflow.NewFlow(1, []bltflow.ActionInfo{{Name: "prepare"}}, actionFactory, cliRunnerFactory)
	err = prepareActionFlow.Run(false)
	if err != nil {
		panic(err)
	}

	if !config.UsingLegacyManifest {
		uploadCloudConfigActionFlow := bltflow.NewFlow(2, []bltflow.ActionInfo{{Name: "upload_cloud_config"}}, actionFactory, cliRunnerFactory)
		err := uploadCloudConfigActionFlow.Run(false)
		if err != nil {
			panic(err)
		}
	}

	randomizer := bltflow.NewRandomizer(actionFactory, cliRunnerFactory, fs, logger)
	if len(os.Args) == 3 {
		err := randomizer.Configure(os.Args[2])
		if err != nil {
			panic(err)
		}
	} else {
		err := randomizer.Prepare(config.Flows, config.NumberOfDeployments)
		if err != nil {
			panic(err)
		}
	}

	doneCh := make(chan error)
	for i := 0; i < config.NumberOfDeployments; i++ {
		go func(i int) {
			doneCh <- randomizer.RunFlow(i, config.UsingLegacyManifest)
		}(i)
	}

	for i := 0; i < config.NumberOfDeployments; i++ {
		err := <-doneCh
		if err != nil {
			panic(err)
		}
	}

	println("Done!")
}
func main() {
	if len(os.Args) < 2 || len(os.Args) > 3 {
		println("Usage: bft path/to/config.json seed")
		os.Exit(1)
	}

	logger := boshlog.NewLogger(boshlog.LevelDebug)
	fs := boshsys.NewOsFileSystem(logger)
	cmdRunner := boshsys.NewExecCmdRunner(logger)

	testConfig := bftconfig.NewConfig(fs)
	err := testConfig.Load(os.Args[1])
	if err != nil {
		panic(err)
	}

	envConfig := bltconfig.NewConfig(fs)
	err = envConfig.Load(os.Args[1])
	if err != nil {
		panic(err)
	}

	assetsProvider := bltassets.NewProvider(envConfig.AssetsPath)

	logger.Debug("main", "Setting up environment")

	environmentProvider := bltenv.NewProvider(envConfig, fs, cmdRunner, assetsProvider)
	environment := environmentProvider.Get()

	if !testConfig.GenerateManifestOnly {
		err = environment.Setup()
		if err != nil {
			panic(err)
		}
		defer environment.Shutdown()
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		environment.Shutdown()
		os.Exit(1)
	}()

	cliRunnerFactory := bltclirunner.NewFactory(envConfig.CliCmd, cmdRunner, fs)

	var directorInfo bltaction.DirectorInfo
	if testConfig.GenerateManifestOnly {
		directorInfo = bltaction.DirectorInfo{
			UUID: "blah",
			URL:  "xxx",
		}
	} else {
		directorInfo, err = bltaction.NewDirectorInfo(environment.DirectorURL(), cliRunnerFactory)
	}

	if err != nil {
		panic(err)
	}
	cliRunner := cliRunnerFactory.Create()
	cliRunner.Configure()
	defer cliRunner.Clean()

	if !testConfig.GenerateManifestOnly {
		logger.Debug("main", "Preparing to deploy")
		preparer := bftdeployment.NewPreparer(directorInfo, cliRunner, fs, assetsProvider)
		err = preparer.Prepare()
		if err != nil {
			panic(err)
		}
	}

	logger.Debug("main", "Starting deploy")
	renderer := bftdeployment.NewRenderer(fs)

	var seed int64
	if len(os.Args) == 3 {
		seed, _ = strconv.ParseInt(os.Args[2], 10, 64)
	} else {
		seed = time.Now().Unix()
	}

	logger.Info("main", "Seeding with %d", seed)
	rand.Seed(seed)

	nameGenerator := bftnamegen.NewNameGenerator()
	decider := bftdecider.NewRandomDecider()

	ipPoolProvider := bftnetwork.NewIpPoolProvider()
	networksAssigner := bftnetwork.NewAssigner(testConfig.Parameters.Networks, nameGenerator, ipPoolProvider, decider, logger)
	parameterProvider := bftparam.NewParameterProvider(testConfig.Parameters, nameGenerator, decider, networksAssigner, logger)
	inputGenerator := bftdeployment.NewInputGenerator(testConfig.Parameters, parameterProvider, testConfig.NumberOfConsequentDeploys, nameGenerator, decider, logger)
	analyzer := bftanalyzer.NewAnalyzer(logger)

	deployer := bftdeployment.NewDeployer(
		cliRunner,
		directorInfo,
		renderer,
		inputGenerator,
		analyzer,
		fs,
		logger,
		testConfig.GenerateManifestOnly,
	)
	err = deployer.RunDeploys()
	if err != nil {
		panic(err)
	}

	println("Done!")
}