# Copyright 2017 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Allows to use Clang as a compiler and assembler."""

from starboard.tools.toolchain import abstract
from starboard.tools.toolchain import common


class CompilerBase(object):
  """A base class for Clang-based compilers and assemblers."""

  def __init__(self, **kwargs):
    self._path = common.GetPath('clang', **kwargs)
    self._extra_flags = kwargs.get('extra_flags', [])
    self._defines = kwargs.get('defines', [])

  def GetPath(self):
    return self._path

  def GetExtraFlags(self):
    return self._extra_flags

  def GetMaxConcurrentProcesses(self):
    # Run as much concurrent processes as possible.
    return None

  def GetHeaderDependenciesFilePath(self):
    return '$out.d'

  def GetHeaderDependenciesFormat(self):
    return 'gcc'

  def GetRspFilePath(self):
    # A command line only contains one input and one output file.
    pass

  def GetRspFileContent(self):
    # A command line only contains one input and one output file.
    pass


def _GetClangCommand(path, language, extra_flags, flags, shell):
  del shell  # Not used.
  return ('{path} -x {language} -MMD -MF $out.d {extra_flags} {flags} -c $in '
          '-o $out'.format(path=path, language=language,
                           extra_flags=extra_flags, flags=flags))


class CCompiler(CompilerBase, abstract.CCompiler):
  """Compiles C sources using Clang."""

  def __init__(self, **kwargs):
    # pylint:disable=useless-super-delegation
    super(CCompiler, self).__init__(**kwargs)

  def GetCommand(self, path, extra_flags, flags, shell):
    return _GetClangCommand(path, 'c', extra_flags, flags, shell)

  def GetDescription(self):
    return 'CC $out'

  def GetFlags(self, defines, include_dirs, cflags):
    define_flags = ['-D{0}'.format(define) for define in defines]
    include_dir_flags = [
        '-I{0}'.format(include_dir) for include_dir in include_dirs
    ]
    return define_flags + include_dir_flags + cflags


class CxxCompiler(CompilerBase, abstract.CxxCompiler):
  """Compiles C++ sources using Clang."""

  def __init__(self, **kwargs):
    # pylint:disable=useless-super-delegation
    super(CxxCompiler, self).__init__(**kwargs)

  def GetCommand(self, path, extra_flags, flags, shell):
    return _GetClangCommand(path, 'c++', extra_flags, flags, shell)

  def GetDescription(self):
    return 'CXX $out'

  def GetFlags(self, defines, include_dirs, cflags):
    define_flags = [
        '-D{0}'.format(define) for define in self._defines + defines
    ]
    include_dir_flags = [
        '-I{0}'.format(include_dir) for include_dir in include_dirs
    ]
    return define_flags + include_dir_flags + cflags


class ObjectiveCxxCompiler(CompilerBase, abstract.ObjectiveCxxCompiler):
  """Compiles Objective-C++ sources using Clang."""

  def __init__(self, **kwargs):
    # pylint:disable=useless-super-delegation
    super(ObjectiveCxxCompiler, self).__init__(**kwargs)

  def GetCommand(self, path, extra_flags, flags, shell):
    return _GetClangCommand(path, 'objective-c++', extra_flags, flags, shell)

  def GetDescription(self):
    return 'OBJCXX $out'

  def GetFlags(self, defines, include_dirs, cflags):
    define_flags = [
        '-D{0}'.format(define) for define in self._defines + defines
    ]
    include_dir_flags = [
        '-I{0}'.format(include_dir) for include_dir in include_dirs
    ]
    return define_flags + include_dir_flags + cflags


class AssemblerWithCPreprocessor(CompilerBase,
                                 abstract.AssemblerWithCPreprocessor):
  """Compiles assembler sources that contain C preprocessor directives."""

  def __init__(self, **kwargs):
    # pylint:disable=useless-super-delegation
    super(AssemblerWithCPreprocessor, self).__init__(**kwargs)

  def GetCommand(self, path, extra_flags, flags, shell):
    return _GetClangCommand(path, 'assembler-with-cpp', extra_flags, flags,
                            shell)

  def GetDescription(self):
    return 'ASM $out'

  def GetFlags(self, defines, include_dirs, cflags):
    define_flags = [
        '-D{0}'.format(define) for define in self._defines + defines
    ]
    include_dir_flags = [
        '-I{0}'.format(include_dir) for include_dir in include_dirs
    ]
    return define_flags + include_dir_flags + cflags
