#! /usr/bin/env python

from abjad.tools import iotools
from abjad.tools.mathtools import greatest_common_divisor
import os


def _reindent_3_spaces_as_4():
   reindented = [ ]
   indented = [ ]
   skipped = [ ]
   for path, subdirectories, files in os.walk('.'):
      for file in files:
         if not file.startswith('__') and (file.endswith('.py') or file.endswith('.rst.raw')):
            _strip_trailing_whitespace(file, path)
            gcd = _find_indent_gcd(file, path)
            if gcd == 1:
               inconsistencies = _find_inconsistent_indents(file, path)
               skipped.append((os.path.join(path, file), inconsistencies))
            elif gcd == 4:
               indented.append(os.path.join(path, file))
            elif gcd == 3:
               _reindent(file, path)
               reindented.append(os.path.join(path, file))
   _print_results(reindented, indented, skipped)


def _strip_trailing_whitespace(file, path):
   filepath = os.path.join(path, file)
   f = open(filepath, 'r')
   lines = f.read().split('\n')
   f.close()
   for i, line in enumerate(lines):
      lines[i] = line.rstrip()
#      if not len(line.lstrip()):
#         lines[i] = ''
#      else:
#         lines[i] = line.rstrip()
   f = open(filepath, 'w')
   f.write('\n'.join(lines))
   f.close()


def _find_indent_gcd(file, path):
   indents = [ ]
   filepath = os.path.join(path, file)
   f = open(filepath, 'r')
   lines = f.read().split('\n')
   f.close()
   for i, line in enumerate(lines):
      if 0 < len(line.lstrip()):
         indent = len(line) - len(line.lstrip())
         if 0 < indent:
            indents.append(indent)
   if indents:
      return greatest_common_divisor(*indents)
   else:
      return 4 # nothing indented, so ignore


def _find_inconsistent_indents(file, path):
   inconsistencies = [ ]
   filepath = os.path.join(path, file)
   f = open(filepath, 'r')
   lines = f.read().split('\n')
   f.close()
   for i, line in enumerate(lines):
      if 0 < len(line.lstrip()):
         indent = len(line) - len(line.lstrip())
         if 0 < indent:
            if 0 < (indent % 3):
               inconsistencies.append(i)
   return inconsistencies


def _reindent(file, path):
   filepath = os.path.join(path, file)
   f = open(filepath, 'r')
   lines = f.read().split('\n')
   f.close()
   for i, line in enumerate(lines):
      indent = len(line) - len(line.lstrip())
      div, mod = divmod(indent, 3)
      if mod != 0:
          print 'Unexpected indent (%d, %d) in %s:%d' % (div, mod, filepath, mod)
          if 0 < i:
              print '%d:\t"%s"' % (i - 1, lines[i - 1])
          print '%d:\t"%s"' % (i, line)
          if line != lines[-1]:
              print '%d:\t"%s"' % (i + 1, lines[i + 1])
          raise Exception()
      lines[i] = lines[i].replace('   ' * div, '    ' * div)
   f = open(filepath, 'w')
   f.write('\n'.join(lines))
   f.close()


def _print_results(reindented, indented, skipped):
   print '%d FILE(S) REINDENTED' % len(reindented)
   for x in reindented:
      print '\t%s' % x
   print '%d FILE(S) ALREADY INDENTED' % len(indented)
   for x in indented:
      print '\t%s' % x
   print '%d FILE(S) SKIPPED DUE TO INCONSISTENT INDENTATION' % len(skipped)
   for x in skipped:
      print '\t%s' % x[0]
      print '\t\t@ %s' % ', '.join([str(line_number + 1) for line_number in x[1]])
              

if __name__ == '__main__':
   iotools.clear_terminal()   
   _reindent_3_spaces_as_4()
   print ''

