#!/usr/bin/env python
# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
# This python script creates a version string in a C++ file.

import hashlib
import os
import sys
import time
from optparse import OptionParser
import utils


def debugLog(message):
    print >> sys.stderr, message
    sys.stderr.flush()


# When these files change, snapshots created by the VM are potentially no longer
# backwards-compatible.
VM_SNAPSHOT_FILES = [
    # Header files.
    'clustered_snapshot.h',
    'datastream.h',
    'image_snapshot.h',
    'object.h',
    'raw_object.h',
    'snapshot.h',
    'snapshot_ids.h',
    'symbols.h',
    # Source files.
    'clustered_snapshot.cc',
    'dart.cc',
    'dart_api_impl.cc',
    'image_snapshot.cc',
    'object.cc',
    'raw_object.cc',
    'raw_object_snapshot.cc',
    'snapshot.cc',
    'symbols.cc',
]


def MakeVersionString(quiet, no_git_hash, custom_for_pub=None):
    channel = utils.GetChannel()
    if custom_for_pub and channel == 'be':
        latest = utils.GetLatestDevTag()
        if not latest:
            # If grabbing the dev tag fails, then fall back on the VERSION file.
            latest = utils.GetSemanticSDKVersion(no_git_hash=True)
        if no_git_hash:
            version_string = ("%s.%s" % (latest, custom_for_pub))
        else:
            git_hash = utils.GetShortGitHash()
            version_string = ("%s.%s-%s" % (latest, custom_for_pub, git_hash))
        # TODO(athom): remove the custom 2.5.0 logic post release.
        # For 2.5.0, we want flutter to claim Dart is 2.5.0 even before it is
        # decided what exactly 2.5.0 will be. Dart & Flutter stable releases
        # will be synced, so that what will be released as Dart 2.5.0 will also
        # be what will be packaged with Flutter.
        version = utils.ReadVersionFile()
        custom_version_string = "%s.%s.%s" % (version.major, version.minor, version.patch)
        if custom_version_string == "2.5.0" and custom_for_pub == "flutter":
            version_string = "2.5.0"


    else:
        version_string = utils.GetSemanticSDKVersion(no_git_hash=no_git_hash)
    if not quiet:
        debugLog("Returning version string: %s " % version_string)
    return version_string


def MakeSnapshotHashString():
    vmhash = hashlib.md5()
    for vmfilename in VM_SNAPSHOT_FILES:
        vmfilepath = os.path.join(utils.DART_DIR, 'runtime', 'vm', vmfilename)
        with open(vmfilepath) as vmfile:
            vmhash.update(vmfile.read())
    return vmhash.hexdigest()


def MakeFile(quiet,
             output_file,
             input_file,
             no_git_hash,
             custom_for_pub,
             version_file=None):
    if version_file:
        version_string = utils.GetVersion(no_git_hash, version_file)
    else:
        version_string = MakeVersionString(quiet, no_git_hash, custom_for_pub)

    version_cc_text = open(input_file).read()
    version_cc_text = version_cc_text.replace("{{VERSION_STR}}", version_string)
    version_time = utils.GetGitTimestamp()
    if no_git_hash or version_time == None:
        version_time = "Unknown timestamp"
    version_cc_text = version_cc_text.replace("{{COMMIT_TIME}}", version_time)
    abi_version = utils.GetAbiVersion(version_file)
    version_cc_text = version_cc_text.replace("{{ABI_VERSION}}", abi_version)
    oldest_supported_abi_version = utils.GetOldestSupportedAbiVersion(
        version_file)
    version_cc_text = version_cc_text.replace(
        "{{OLDEST_SUPPORTED_ABI_VERSION}}", oldest_supported_abi_version)
    snapshot_hash = MakeSnapshotHashString()
    version_cc_text = version_cc_text.replace("{{SNAPSHOT_HASH}}",
                                              snapshot_hash)
    open(output_file, 'w').write(version_cc_text)
    return True


def main(args):
    try:
        # Parse input.
        parser = OptionParser()
        parser.add_option(
            "--custom_for_pub",
            action="store",
            type="string",
            help=("Generates a version string that works with pub that includes"
                  "the given string. This is silently ignored on channels other"
                  "than be"))
        parser.add_option(
            "--input",
            action="store",
            type="string",
            help="input template file.")
        parser.add_option(
            "--no_git_hash",
            action="store_true",
            default=False,
            help="Don't try to determine svn revision")
        parser.add_option(
            "--output", action="store", type="string", help="output file name")
        parser.add_option(
            "-q",
            "--quiet",
            action="store_true",
            default=False,
            help="disable console output")
        parser.add_option(
            "--version-file",
            action="store",
            type="string",
            default=None,
            help="Version file")

        (options, args) = parser.parse_args()

        # If there is no input template, then write the bare version string to
        # options.output. If there is no options.output, then write the version
        # string to stdout.
        if not options.input:
            version_string = MakeVersionString(
                options.quiet, options.no_git_hash, options.custom_for_pub)
            if options.output:
                open(options.output, 'w').write(version_string)
            else:
                print(version_string)
            return 0

        if not options.output:
            sys.stderr.write('--output not specified\n')
            return -1
        if not options.input:
            sys.stderr.write('--input not specified\n')
            return -1

        files = []
        for arg in args:
            files.append(arg)

        if not MakeFile(options.quiet, options.output, options.input,
                        options.no_git_hash, options.custom_for_pub,
                        options.version_file):
            return -1

        return 0
    except Exception as inst:
        sys.stderr.write('make_version.py exception\n')
        sys.stderr.write(str(inst))
        sys.stderr.write('\n')
        return -1


if __name__ == '__main__':
    exit_code = main(sys.argv)
    sys.exit(exit_code)
