#!/usr/bin/env python
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

import os
import subprocess
import sys

import util
from simplebuild import *

class GetFileInfoRule(SimpleAsyncRule):
    """
    Rule which synchronizes the state of external file.
    """

    def __init__(self, path):
        self.path = str(path)

    def run(self):
        util.note("getting file info: %r" % (self.path,))
        return util.get_stat_info(self.path)

    def is_data_valid(self, engine, data):
        # Check if the current info is up-to-date.
        util.note("checking file info: %r" % (self.path,))
        return util.get_stat_info(self.path) == data
        
class GetDirectoryContentsRule(SimpleAsyncRule):
    def __init__(self, path):
        self.path = path

    def start(self, engine):
        # Get the file info for the directory, to ensure we treat the external
        # directory as an input.
        engine.task_needs_input(self, GetFileInfoRule.asKey(self.path))

    def provide_data(self, engine, input_id, data):
        pass

    def run(self):
        util.note("listing directory contents: %r" % (str(self.path),))
        try:
            return sorted(os.listdir(self.path))
        except OSError:
            return []
    
class SpawnJobRule(SimpleAsyncRule):
    def __init__(self, args, input_files, output_files, other_inputs=()):
        self.args = list(args)
        self.input_files = list(input_files)
        self.output_files = list(output_files)
        self.other_inputs = list(other_inputs)

    def start(self, engine):
        # Request all of the inputs.
        for path in self.input_files:
            engine.task_needs_input(self, GetFileInfoRule.asKey(path))
        for key in self.other_inputs:
            engine.task_needs_input(self, key)

    def provide_data(self, engine, input_id, data):
        pass
        
    def run(self):
        try:
            util.message(' '.join(self.args))
            subprocess.check_call(self.args)
        except:
            util.error("error: command failed: %s" % (' '.join(self.args),))
            return { "error" : True }

        # Get the file info on all of the output files.
        output_infos = [util.get_stat_info(path)
                       for path in self.output_files]
        return { "output_info" : output_infos }

class BuildDirectoryRule(SimpleRule):
    sources_list_ID = 0
    compile_ID = 1
    link_ID = 2

    def __init__(self, path):
        self.path = path
        self.sources = None

    def start(self, engine):
        # Request the source files for the current directory.
        engine.task_needs_input(self, GetDirectoryContentsRule.asKey(self.path),
                                self.sources_list_ID)

    def provide_data(self, engine, input_id, result):
        if input_id == self.sources_list_ID:
            self.sources = [str(name)
                            for name in result
                            if name.endswith(".c")]
            util.note("building sources: %r" % (self.sources),)

            # Request compilation of all the sources.
            objects = []
            objects_keys = []
            for name in self.sources:
                input = os.path.join(self.path, name)
                output = os.path.join(self.path, "%s.o" % name)
                objects.append(output)

                cmd = ['cc', '-c', '-o', output, input]
                job = SpawnJobRule.asKey(cmd, [input], [output])
                engine.task_needs_input(self, job, self.compile_ID)
                objects_keys.append(job)

            # Request a link of the objects.
            output = os.path.join(self.path, os.path.basename(self.path))
            cmd = ['cc', '-o', output] + objects
            job = SpawnJobRule.asKey(cmd, [], [output], objects_keys)
            engine.task_needs_input(self, job, self.link_ID)

    def inputs_available(self, engine):
        engine.task_is_complete(self, "done.")

# Get the input path.
_,path = sys.argv

# Build the app.
engine = DataDrivenEngine(globals())
engine.attach_db(".build.db")
result = engine.build(BuildDirectoryRule.asKey(path))
print result
