(function(exports){
	'use strict'
	
	
	var flash_str;
	
	
	function stdout(cb, text)
	{
		text=text.replace(/\r/g, '\n');
		var nl;
		while ( (nl=text.indexOf('\n')) >= 0 )
		{
			cb(flash_str + text.substring(0, nl));
			flash_str="";
			text=text.substring(nl+1);
		}
		flash_str=text;
	}
	
	
	if (system.os == "linux")
	{
		var flash_ok;
		
		var stdout_line = function(text)
		{
			if (text.length == 0) return;
			
			print("stdout: '"+text+"'\n");
			if (text.match(/Flash written and verified/))
				flash_ok=true;
			
			var p = /^\s*([0-9]+)\/([0-9]+) pages written/.exec(text);
			if (p != null)
				ui.progress(100 * p[1] / p[2]);
		};
		
		
		exports.write = function(filename, reset, addr) {
			if (! addr) addr="0x08000000";
			try
			{
				flash_ok=false;
				flash_str="";
				var args=[ "write", filename, addr ];
				if (reset) args.unshift("--reset");
				var rv=system.exec("st-flash", args, stdout.bind(null, stdout_line), stdout.bind(null, stdout_line));
				if (rv != 0) throw new Error("errorcode="+rv);
				if (! flash_ok) throw new Error("ok-pattern not found");
			} catch (e)
			{
				print("st-flash error: "+e+"\n");
				return false;
			}
			
			return true;
		};
		
		exports.read = function(filename, addr, size, reset) {
			try
			{
				var args=[ "read", filename, addr, size ];
				if (reset) args.unshift("--reset");
				var rv=system.exec("st-flash", args, print, print);
				if (rv != 0) throw new Error("errorcode="+rv);
			} catch (e)
			{
				print("st-flash error: "+e+"\n");
				return false;
			}
			
			return true;
		};
		
		
		exports.erase = function(reset) {
			try
			{
				var args=[ "erase" ];
				if (reset) args.unshift("--reset");
				var rv=system.exec("st-flash", args, print, print);
				if (rv != 0) throw new Error("errorcode="+rv);
			} catch (e)
			{
				print("st-flash error: "+e+"\n");
				return false;
			}
			
			return true;
		};
	} else
	if (system.os == "windows")
	{
		var flash_ok;
		
		var stdout_line = function(text)
		{
			if (text.length == 0) return;
			
			print("stdout: '"+text+"'\n");
			if (text.match(/^Verification...OK/))
				flash_ok=true; else
			if (text.match(/^Dumping memory to .* succeded$/))
				flash_ok=true; else
			if (text.match(/^Flash memory erased.$/))
				flash_ok=true;
		};
		
		
		exports.write = function(filename, reset, addr) {
			if (! addr) addr="0x08000000";
			try
			{
				flash_ok=false;
				flash_str="";
				var rv=system.exec("flashers/stm32-stlink/ST-LINK_CLI.exe", [ "-c", "SWD", reset ? "UR" : "HOTPLUG", "-NoPrompt", "-V", "-P", filename, addr, "-Run" ], stdout.bind(null, stdout_line), stdout.bind(null, stdout_line));
				// Убрано из-за некорректной работы с пустой УСПД
				// if (rv != 0) throw new Error("errorcode="+rv);
				if (! flash_ok) throw new Error("ok-pattern not found");
			} catch (e)
			{
				print("ST-LINK_CLI error: "+e+"\n");
				return false;
			}
			
			return true;
		};
		
		
		exports.read = function(filename, addr, size, reset) {
			try
			{
				flash_ok=false;
				flash_str="";
				var rv=system.exec("flashers/stm32-stlink/ST-LINK_CLI.exe", [ "-c", "SWD", reset ? "UR" : "HOTPLUG", "-NoPrompt", "-Dump", addr, size, filename, "-Run" ], stdout.bind(null, stdout_line), stdout.bind(null, stdout_line));
				// Убрано из-за некорректной работы с пустой УСПД
				// if (rv != 0) throw new Error("errorcode="+rv);
				if (! flash_ok) throw new Error("ok-pattern not found");
			} catch (e)
			{
				print("ST-LINK_CLI error: "+e+"\n");
				return false;
			}
			
			return true;
		};
		
		
		exports.erase = function(reset) {
			try
			{
				flash_ok=false;
				flash_str="";
				var rv=system.exec("flashers/stm32-stlink/ST-LINK_CLI.exe", [ "-c", "SWD", reset ? "UR" : "HOTPLUG", "-NoPrompt", "-ME", "-Halt" ], stdout.bind(null, stdout_line), stdout.bind(null, stdout_line));
				// Убрано из-за некорректной работы с пустой УСПД
				// if (rv != 0) throw new Error("errorcode="+rv);
				if (! flash_ok) throw new Error("ok-pattern not found");
			} catch (e)
			{
				print("ST-LINK_CLI error: "+e+"\n");
				return false;
			}
			
			return true;
		};
	} else
	{
		throw new Error("Bad OS");
	}
	
})(typeof exports === 'undefined' ? this['_stm32_js']={} : exports);
