#! /usr/bin/env python

#   Copyright 2016 WebAssembly Community Group participants
#
#   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.

import filecmp
import os
import shutil
import subprocess
import sys
import tempfile


def _open_archive(tarfile, tmp_dir):
  with tempfile.TemporaryFile(mode='w+') as f:
    try:
      subprocess.check_call(['tar', '-xvf', tarfile], cwd=tmp_dir, stdout=f)
    except:
      f.seek(0)
      sys.stderr.write(f.read())
      raise
  return os.listdir(tmp_dir)


def _files_same(dir1, dir2, basenames):
  diff = filecmp.cmpfiles(dir1, dir2, basenames)
  return 0 == len(diff[1] + diff[2])


def _dirs_same(dir1, dir2, basenames):
  for d in basenames:
    left = os.path.join(dir1, d)
    right = os.path.join(dir2, d)
    if not (os.path.isdir(left) and os.path.isdir(right)):
      return False
    diff = filecmp.dircmp(right, right)
    if 0 != len(diff.left_only + diff.right_only + diff.diff_files +
                diff.common_funny + diff.funny_files):
      return False
  return True


def _move_files(dirfrom, dirto, basenames):
  for f in basenames:
    from_file = os.path.join(dirfrom, f)
    to_file = os.path.join(dirto, f)
    if os.path.isfile(to_file):
      os.path.remove(to_file)
    shutil.move(from_file, to_file)


def _move_dirs(dirfrom, dirto, basenames):
    for d in basenames:
      from_dir = os.path.join(dirfrom, d)
      to_dir = os.path.join(dirto, d)
      if os.path.isdir(to_dir):
        shutil.rmtree(to_dir)
      shutil.move(from_dir, to_dir)


def untar(tarfile, outdir):
  """Returns True if untar content differs from pre-existing outdir content."""
  tmpdir = tempfile.mkdtemp()
  try:
    untared = _open_archive(tarfile, tmpdir)
    files = [f for f in untared if os.path.isfile(os.path.join(tmpdir, f))]
    dirs = [d for d in untared if os.path.isdir(os.path.join(tmpdir, d))]
    assert len(files) + len(dirs) == len(untared), 'Only files and directories'
    if _files_same(tmpdir, outdir, files) and _dirs_same(tmpdir, outdir, dirs):
      # Nothing new or different in the tarfile.
      return False
    # Some or all of the files / directories are new.
    _move_files(tmpdir, outdir, files)
    _move_dirs(tmpdir, outdir, dirs)
    return True
  finally:
    if os.path.isdir(tmpdir):
      shutil.rmtree(tmpdir)


def split_wast(wast):
  # .wast files can contain multiple modules, and assertions for each one.
  # this splits out a wast into [(module, assertions), ..]
  # we ignore module invalidity tests here.
  wast = open(wast).read()
  ret = []

  def to_end(j):
    depth = 1
    while depth > 0 and j < len(wast):
      if wast[j] == '"':
        while 1:
          j = wast.find('"', j + 1)
          if wast[j - 1] == '\\':
            continue
          break
        assert j > 0
      elif wast[j] == '(':
        depth += 1
      elif wast[j] == ')':
        depth -= 1
      elif wast[j] == ';' and wast[j + 1] == ';':
        j = wast.find('\n', j)
      j += 1
    return j

  i = 0
  while i >= 0:
    start = wast.find('(', i)
    if start >= 0 and wast[start + 1] == ';':
      # block comment
      i = wast.find(';)', start + 2)
      assert i > 0, wast[start:]
      i += 2
      continue
    skip = wast.find(';', i)
    if skip >= 0 and skip < start and skip + 1 < len(wast):
      if wast[skip + 1] == ';':
        i = wast.find('\n', i) + 1
        continue
    if start < 0:
      break
    i = to_end(start + 1)
    chunk = wast[start:i]
    if chunk.startswith('(module'):
      ret += [(chunk, [])]
    elif chunk.startswith('(assert_invalid'):
      continue
    elif chunk.startswith(('(assert', '(invoke')):
      ret[-1][1].append(chunk)
  return ret


def run_command(cmd, expected_status=0, stderr=None, expected_err=None):
  if expected_err is not None:
    assert stderr == subprocess.PIPE or stderr is None,\
        "Can't redirect stderr if using expected_err"
    stderr = subprocess.PIPE
  print 'executing: ', ' '.join(cmd)
  proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr)
  out, err = proc.communicate()
  if proc.returncode != expected_status:
    raise Exception(('run_command failed', err))
  if expected_err is not None and err != expected_err:
    raise Exception(('run_command unexpected stderr',
                     "expected '%s', actual '%s'" % (expected_err, err)))
  return out
