Initialize a new Zappa project by creating a new zappa_settings.json in a guided process.

        This should probably be broken up into few separate componants once it's stable.
        Testing these inputs requires monkeypatching with mock, which isn't pretty.

def init(self, settings_file="zappa_settings.json"):
        """
        Initialize a new Zappa project by creating a new zappa_settings.json in a guided process.

        This should probably be broken up into few separate componants once it's stable.
        Testing these inputs requires monkeypatching with mock, which isn't pretty.

        """

        # Make sure we're in a venv.
        self.check_venv()

        # Ensure that we don't already have a zappa_settings file.
        if os.path.isfile(settings_file):
            raise ClickException("This project already has a " + click.style("{0!s} file".format(settings_file), fg="red", bold=True) + "!")

        # Explain system.
        click.echo(click.style(u"""\n███████╗ █████╗ ██████╗ ██████╗  █████╗
╚══███╔╝██╔══██╗██╔══██╗██╔══██╗██╔══██╗
  ███╔╝ ███████║██████╔╝██████╔╝███████║
 ███╔╝  ██╔══██║██╔═══╝ ██╔═══╝ ██╔══██║
███████╗██║  ██║██║     ██║     ██║  ██║
╚══════╝╚═╝  ╚═╝╚═╝     ╚═╝     ╚═╝  ╚═╝\n""", fg='green', bold=True))

        click.echo(click.style("Welcome to ", bold=True) + click.style("Zappa", fg='green', bold=True) + click.style("!\n", bold=True))
        click.echo(click.style("Zappa", bold=True) + " is a system for running server-less Python web applications"
                                                     " on AWS Lambda and AWS API Gateway.")
        click.echo("This `init` command will help you create and configure your new Zappa deployment.")
        click.echo("Let's get started!\n")

        # Create Env
        while True:
            click.echo("Your Zappa configuration can support multiple production stages, like '" +
                       click.style("dev", bold=True)  + "', '" + click.style("staging", bold=True)  + "', and '" +
                       click.style("production", bold=True)  + "'.")
            env = input("What do you want to call this environment (default 'dev'): ") or "dev"
            try:
                self.check_stage_name(env)
                break
            except ValueError:
                click.echo(click.style("Stage names must match a-zA-Z0-9_", fg="red"))

        # Detect AWS profiles and regions
        # If anyone knows a more straightforward way to easily detect and parse AWS profiles I'm happy to change this, feels like a hack
        session = botocore.session.Session()
        config  = session.full_config
        profiles = config.get("profiles", {})
        profile_names = list(profiles.keys())

        click.echo("\nAWS Lambda and API Gateway are only available in certain regions. "\
                   "Let's check to make sure you have a profile set up in one that will work.")

        if not profile_names:
            profile_name, profile = None, None
            click.echo("We couldn't find an AWS profile to use. Before using Zappa, you'll need to set one up. See here for more info: {}"
                       .format(click.style(BOTO3_CONFIG_DOCS_URL, fg="blue", underline=True)))
        elif len(profile_names) == 1:
            profile_name = profile_names[0]
            profile = profiles[profile_name]
            click.echo("Okay, using profile {}!".format(click.style(profile_name, bold=True)))
        else:
            if "default" in profile_names:
                default_profile = [p for p in profile_names if p == "default"][0]
            else:
                default_profile = profile_names[0]

            while True:
                profile_name = input("We found the following profiles: {}, and {}. "\
                                         "Which would you like us to use? (default '{}'): "
                                         .format(
                                             ', '.join(profile_names[:-1]),
                                             profile_names[-1],
                                             default_profile
                                         )) or default_profile
                if profile_name in profiles:
                    profile = profiles[profile_name]
                    break
                else:
                    click.echo("Please enter a valid name for your AWS profile.")

        profile_region = profile.get("region") if profile else None

        # Create Bucket
        click.echo("\nYour Zappa deployments will need to be uploaded to a " + click.style("private S3 bucket", bold=True)  + ".")
        click.echo("If you don't have a bucket yet, we'll create one for you too.")
        default_bucket = "zappa-" + ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(9))
        while True:
            bucket = input("What do you want to call your bucket? (default '%s'): " % default_bucket) or default_bucket

            if is_valid_bucket_name(bucket):
                break

            click.echo(click.style("Invalid bucket name!", bold=True))
            click.echo("S3 buckets must be named according to the following rules:")
            click.echo("""* Bucket names must be unique across all existing bucket names in Amazon S3.
* Bucket names must comply with DNS naming conventions.
* Bucket names must be at least 3 and no more than 63 characters long.
* Bucket names must not contain uppercase characters or underscores.
* Bucket names must start with a lowercase letter or number.
* Bucket names must be a series of one or more labels. Adjacent labels are separated
  by a single period (.). Bucket names can contain lowercase letters, numbers, and
  hyphens. Each label must start and end with a lowercase letter or a number.
* Bucket names must not be formatted as an IP address (for example, 192.168.5.4).
* When you use virtual hosted–style buckets with Secure Sockets Layer (SSL), the SSL
  wildcard certificate only matches buckets that don't contain periods. To work around
  this, use HTTP or write your own certificate verification logic. We recommend that
  you do not use periods (".") in bucket names when using virtual hosted–style buckets.
""")


        # Detect Django/Flask
        try: # pragma: no cover
            import django
            has_django = True
        except ImportError as e:
            has_django = False

        try: # pragma: no cover
            import flask
            has_flask = True
        except ImportError as e:
            has_flask = False

        print('')
        # App-specific
        if has_django: # pragma: no cover
            click.echo("It looks like this is a " + click.style("Django", bold=True)  + " application!")
            click.echo("What is the " + click.style("module path", bold=True)  + " to your projects's Django settings?")
            django_settings = None

            matches = detect_django_settings()
            while django_settings in [None, '']:
                if matches:
                    click.echo("We discovered: " + click.style(', '.join('{}'.format(i) for v, i in enumerate(matches)), bold=True))
                    django_settings = input("Where are your project's settings? (default '%s'): " % matches[0]) or matches[0]
                else:
                    click.echo("(This will likely be something like 'your_project.settings')")
                    django_settings = input("Where are your project's settings?: ")
            django_settings = django_settings.replace("'", "")
            django_settings = django_settings.replace('"', "")
        else:
            matches = None
            if has_flask:
                click.echo("It looks like this is a " + click.style("Flask", bold=True)  + " application.")
                matches = detect_flask_apps()
            click.echo("What's the " + click.style("modular path", bold=True)  + " to your app's function?")
            click.echo("This will likely be something like 'your_module.app'.")
            app_function = None
            while app_function in [None, '']:
                if matches:
                    click.echo("We discovered: " + click.style(', '.join('{}'.format(i) for v, i in enumerate(matches)), bold=True))
                    app_function = input("Where is your app's function? (default '%s'): " % matches[0]) or matches[0]
                else:
                    app_function = input("Where is your app's function?: ")
            app_function = app_function.replace("'", "")
            app_function = app_function.replace('"', "")

        # TODO: Create VPC?
        # Memory size? Time limit?
        # Domain? LE keys? Region?
        # 'Advanced Settings' mode?

        # Globalize
        click.echo("\nYou can optionally deploy to " + click.style("all available regions", bold=True)  + " in order to provide fast global service.")
        click.echo("If you are using Zappa for the first time, you probably don't want to do this!")
        global_deployment = False
        while True:
            global_type = input("Would you like to deploy this application " + click.style("globally", bold=True)  + "? (default 'n') [y/n/(p)rimary]: ")
            if not global_type:
                break
            if global_type.lower() in ["y", "yes", "p", "primary"]:
                global_deployment = True
                break
            if global_type.lower() in ["n", "no"]:
                global_deployment = False
                break

        # The given environment name
        zappa_settings = {
            env: {
                'profile_name': profile_name,
                's3_bucket': bucket,
                'runtime': get_venv_from_python_version(),
                'project_name': self.get_project_name()
            }
        }

        if profile_region:
            zappa_settings[env]['aws_region'] = profile_region

        if has_django:
            zappa_settings[env]['django_settings'] = django_settings
        else:
            zappa_settings[env]['app_function'] = app_function

        # Global Region Deployment
        if global_deployment:
            additional_regions = [r for r in API_GATEWAY_REGIONS if r != profile_region]
            # Create additional stages
            if global_type.lower() in ["p", "primary"]:
                additional_regions = [r for r in additional_regions if '-1' in r]

            for region in additional_regions:
                env_name = env + '_' + region.replace('-', '_')
                g_env = {
                    env_name: {
                        'extends': env,
                        'aws_region': region
                    }
                }
                zappa_settings.update(g_env)

        import json as json # hjson is fine for loading, not fine for writing.
        zappa_settings_json = json.dumps(zappa_settings, sort_keys=True, indent=4)

        click.echo("\nOkay, here's your " + click.style("zappa_settings.json", bold=True) + ":\n")
        click.echo(click.style(zappa_settings_json, fg="yellow", bold=False))

        confirm = input("\nDoes this look " + click.style("okay", bold=True, fg="green")  + "? (default 'y') [y/n]: ") or 'yes'
        if confirm[0] not in ['y', 'Y', 'yes', 'YES']:
            click.echo("" + click.style("Sorry", bold=True, fg='red') + " to hear that! Please init again.")
            return

        # Write
        with open("zappa_settings.json", "w") as zappa_settings_file:
            zappa_settings_file.write(zappa_settings_json)

        if global_deployment:
            click.echo("\n" + click.style("Done", bold=True) + "! You can also " + click.style("deploy all", bold=True)  + " by executing:\n")
            click.echo(click.style("\t$ zappa deploy --all", bold=True))

            click.echo("\nAfter that, you can " + click.style("update", bold=True) + " your application code with:\n")
            click.echo(click.style("\t$ zappa update --all", bold=True))
        else:
            click.echo("\n" + click.style("Done", bold=True) + "! Now you can " + click.style("deploy", bold=True)  + " your Zappa application by executing:\n")
            click.echo(click.style("\t$ zappa deploy %s" % env, bold=True))

            click.echo("\nAfter that, you can " + click.style("update", bold=True) + " your application code with:\n")
            click.echo(click.style("\t$ zappa update %s" % env, bold=True))

        click.echo("\nTo learn more, check out our project page on " + click.style("GitHub", bold=True) +
                   " here: " + click.style("https://github.com/Miserlou/Zappa", fg="cyan", bold=True))
        click.echo("and stop by our " + click.style("Slack", bold=True) + " channel here: " +
                   click.style("https://slack.zappa.io", fg="cyan", bold=True))
        click.echo("\nEnjoy!,")
        click.echo(" ~ Team " + click.style("Zappa", bold=True) + "!")

        return