(function() {

/*****************************************************************************
* *
* EDIT CONSTANTS BELOW TO MATCH YOUR MACHINE SETUP *
* *
* Cygwin 1.7 and Ruby must be installed first (install using setup-1.7.exe) *
* Unix machines DO NOT need Cygwin. Instead use /usr/bin as CYGWIN_PATH *
* *
* To install Sass, follow instructions here first: *
* http://www.cygwin.com/ml/cygwin/2007-05/msg00439.html *
* Start Cygwin and run: *
* > gem install haml *
* *
* java executable is recommended to be on PATH, however you can specify *
* a full path below. *
* *
* Remember to escape \ as \\ *
* *
****************************************************************************/

// Download from http://www.java.com/en/download/manual.jsp
const JAVA_PATH = 'java';

// Download from http://yuilibrary.com/downloads/#yuicompressor
const YUI_PATH = 'D:\\Workspace\\assets\\3rdparty\\yuicompressor-2.4.2.jar';

// Download from http://closure-compiler.googlecode.com/files/compiler-latest.zip
const CLOSURE_COMPILER_PATH = 'D:\\Workspace\\assets\\3rdparty\\compiler.jar';

// Download from http://cygwin.com/setup-1.7.exe
const CYGWIN_PATH = 'C:\\bin\\cygwin\\';

/** DON'T EDIT PAST THIS LINE ***********************************************/

var supportedCompilers = { 'yui-css': [JAVA_PATH + ' -jar "' + YUI_PATH + '" --charset utf-8 -v --type=css -o "{1}" "{0}"'],
'yui-js': [JAVA_PATH + ' -jar "' + YUI_PATH + '" --charset utf-8 -v --type=js -o "{1}" "{0}"'],

'closure-compiler-js': [JAVA_PATH + ' -jar "' + CLOSURE_COMPILER_PATH + '" --js "{0}" --js_output_file "{1}"'],

'sass': ['"' + CYGWIN_PATH + 'bin\\sass" --trace --style=compressed "{0}" "{1}"',
'PATH=' + CYGWIN_PATH + 'bin;' + CYGWIN_PATH + 'lib\nNODOSFILEWARNING=1'] };

var knownTypes = { '.uncompressed.css': ['yui-css', '.css'],
'.unprocessed.css': ['yui-css', '.css'],
'.uncompressed.js': ['closure-compiler-js', '.js'],
'.unprocessed.js': ['closure-compiler-js', '.js'],
'.jssrc': ['closure-compiler-js', '.js'],
'.sass': ['sass', '.css'] };

const Cc = Components.classes;
const Ci = Components.interfaces;

if (typeof (extensions) === 'undefined')
window.extensions = {};

if (typeof (window.extensions.compileObserver) === 'undefined')
window.extensions.compileObserver = null;

const INDEX_COMMAND_LINE = 0;
const INDEX_ENVIRONMENT = 1;

const INDEX_COMPILER = 0;
const INDEX_FILE_EXTENSION = 1;

var observerSvc = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);

function ProcessObserver(command, process, callback) {

this._command = command;
this._process = process;

this._callback = (callback || function() {});

observerSvc.addObserver(this, 'run_terminated', false);

try {

this._process.wait(0);
this.cleanUp();

} catch (exception) {};
};

ProcessObserver.prototype.observe = function(child, topic, command) {

if ('run_terminated' === topic &&
this._command === command) {

this.cleanUp();

this._process = null;
}
};

ProcessObserver.prototype.cleanUp = function() {

if (this._command) {

observerSvc.removeObserver(this, 'run_terminated');
this._command = null;
}

if (this._process) {

var processExitCode = process.wait(-1),
processOutput = (this._process.getStdout() || this._process.getStderr());

this._callback(processExitCode, processOutput, this._process);

this._process = null;
}
};

ProcessObserver.prototype.kill = function() {

if (this._command) {

observerSvc.removeObserver(this, 'run_terminated');
this._command = null;
}

if (this._process) {

this._process.kill(-1);
this._process = null;
}
};

if (ko.views.manager &&
ko.views.manager.currentView &&
ko.views.manager.currentView.getAttribute('type') === 'editor' &&
ko.views.manager.currentView.document) {

var view = ko.views.manager.currentView,
document = view.document,
inputFilePath = document.file.path,
inputBaseName = document.file.baseName,
inputDirectoryPath = inputFilePath.substr(0, inputFilePath.length - inputBaseName.length);

for (var knownExtension in knownTypes)
if (knownTypes.hasOwnProperty(knownExtension) &&
inputFilePath.indexOf(knownExtension) === inputFilePath.length - knownExtension.length) {

var outputFilePath = inputFilePath.substr(0, inputFilePath.length - knownExtension.length) + knownTypes[knownExtension][INDEX_FILE_EXTENSION],
outputBaseName = inputBaseName.substr(0, inputBaseName.length - knownExtension.length) + knownTypes[knownExtension][INDEX_FILE_EXTENSION],

compilerName = knownTypes[knownExtension][INDEX_COMPILER],

commandLine = supportedCompilers[compilerName][INDEX_COMMAND_LINE],
commandEnvironment = supportedCompilers[compilerName][INDEX_ENVIRONMENT];

commandLine = commandLine.replace('{0}', inputFilePath, 'g')
.replace('{1}', outputFilePath, 'g');

StatusBar_AddMessage("Compiling '" + inputBaseName + "' using '" + compilerName + "'...", 'run_command', 12500, false);

var runSvc = Cc['@activestate.com/koRunService;1'].getService(Ci.koIRunService);

try {

if (window.extensions.compileObserver)
window.extensions.compileObserver.kill();

var process = runSvc.RunAndNotify(commandLine, inputDirectoryPath, commandEnvironment, null);

window.extensions.compileObserver = new ProcessObserver(commandLine, process, function(processExitCode, processOutput) {

if (processExitCode === 0)
StatusBar_AddMessage("Done compiling '" + inputBaseName + "' to '" + outputBaseName + "'.", 'run_command', 1500, false);
else
ko.dialogs.alert("Error compiling '" + inputBaseName + "' [" + processExitCode + "] using '" + compilerName + "'.",
"Output:\n"
+ processOutput
+ "\n________________________\n\n"
+ "Command line:\n" + commandLine);
});

view.setFocus();

} catch (exception) {

var lastErrorSvc = Cc['@activestate.com/koLastErrorService;1'].getService(Ci.koILastErrorService);

var errorMessage = lastErrorSvc.getLastErrorMessage();
if ( ! errorMessage)
errorMessage = exception;

ko.dialogs.alert('Whoops! Compile encountered an exception:', errorMessage);

throw exception;
}
}
}

})();