#!/usr/bin/python
# Compresses the core Blockly files into a single JavaScript file.
#
# Copyright 2012 Google Inc.
# http://blockly.googlecode.com/
#
# 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.

# This script generates two files:
#   demos/blockly_compressed.js
#   demos/blockly_uncompressed.js
# The compressed file is a concatenation of all of Blockly's core files which
# have been run through Google's Closure Compiler.  This is done using the
# online API (which takes a few seconds and requires an Internet connection).
# The uncompressed file is a script that loads in each of Blockly's core files
# one by one.  This takes much longer for a browser to load, but may be useful
# when debugging code since line numbers are meaningful and variables haven't
# been renamed.  The oncompressed file also allows for a faster developement
# cycle since there is no need to rebuild or recompile, just reload.

import httplib, json, urllib, sys

filenames = [
    'blockly.js',
    'block.js',
    'block_svg.js',
    'bubble.js',
    'comment.js',
    'connection.js',
    'contextmenu.js',
    'field.js',
    'field_dropdown.js',
    'field_checkbox.js',
    'field_colour.js',
    'field_image.js',
    'field_label.js',
    'field_textinput.js',
    'field_variable.js',
    'flyout.js',
    'generator.js',
    'inject.js',
    'input.js',
    'mutator.js',
    'names.js',
    'procedures.js',
    'scrollbar.js',
    'toolbox.js',
    'tooltip.js',
    'trashcan.js',
    'utils.js',
    'variables.js',
    'warning.js',
    'workspace.js',
    'xml.js']

header = ('// Do not edit this file; automatically generated by build.py.\n'
          '"use strict";')

def gen_uncompressed():
  target_filename = 'demos/blockly_uncompressed.js'
  inc = '''%s
document.write('<script type="text/javascript" src="../../../closure-library-read-only/closure/goog/base.js"></script>');
(function() {
  var filenames = %s;
  for (var x = 0; x < filenames.length; x++) {
    document.write('<script type="text/javascript" src="../../core/' + filenames[x] + '"></script>');
  }
})();
''' % (header, filenames)

  f = open(target_filename, 'w')
  f.write(inc)
  f.close()
  print 'SUCCESS: ' + target_filename

def gen_compressed():
  target_filename = 'demos/blockly_compressed.js'
  # Define the parameters for the POST request.
  params = [
      ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),
      ('use_closure_library', 'true'),
      ('output_format', 'json'),
      ('output_info', 'compiled_code'),
      ('output_info', 'warnings'),
      ('output_info', 'errors'),
      ('output_info', 'statistics'),
    ]

  # Read in all the source files.
  for filename in filenames:
    f = open('core/' + filename)
    params.append(('js_code', ''.join(f.readlines())))
    f.close()

  # Send the request to Google.
  headers = { "Content-type": "application/x-www-form-urlencoded" }
  conn = httplib.HTTPConnection('closure-compiler.appspot.com')
  conn.request('POST', '/compile', urllib.urlencode(params), headers)
  response = conn.getresponse()
  json_str = response.read()
  conn.close

  # Parse the JSON response.
  json_data = json.loads(json_str)

  def file_lookup(name):
    if not name.startswith('Input_'):
      return '???'
    n = int(name[6:])
    return filenames[n]

  if json_data.has_key('errors'):
    errors = json_data['errors']
    for error in errors:
      print 'FATAL ERROR'
      print error['error']
      print '%s at line %d:' % (
          file_lookup(error['file']), error['lineno'])
      print error['line']
      print (' ' * error['charno']) + '^'
  else:
    if json_data.has_key('warnings'):
      warnings = json_data['warnings']
      for warning in warnings:
        print 'WARNING'
        print warning['warning']
        print '%s at line %d:' % (
            file_lookup(warning['file']), warning['lineno'])
        print warning['line']
        print (' ' * warning['charno']) + '^'
      print

    code = header + '\n' + json_data['compiledCode']

    stats = json_data['statistics']
    original_b = stats['originalSize']
    compressed_b = stats['compressedSize']
    if original_b > 0 and compressed_b > 0:
      f = open(target_filename, 'w')
      f.write(code)
      f.close()

      original_kb = int(original_b / 1024 + 0.5)
      compressed_kb = int(compressed_b / 1024 + 0.5)
      ratio = int(float(compressed_b) / float(original_b) * 100 + 0.5)
      print 'SUCCESS: ' + target_filename
      print 'Size changed from %d KB to %d KB (%d%%).' % (
          original_kb, compressed_kb, ratio)
    else:
      print 'UNKNOWN ERROR'

if __name__ == '__main__':
  gen_uncompressed()
  gen_compressed()
