package hw.net; import promhx.Deferred; import promhx.Promise; import haxe.Timer; import flash.net.URLRequestMethod; import flash.events.ProgressEvent; import hw.net.manage.ILoaderManager; import flash.utils.ByteArray; import flash.events.Event; class BaseLoader extends Deferred implements ILoader { private static inline var TAG:String = "Loader"; //ToDo: move to LoaderManager public static var urlProcessors(default, null):ArrayString> = new ArrayString>(); public static function prepareUrl(url:String):String { for (p in urlProcessors) url = p(url); return url; } public static var proxy(default, default):String->String; public var timeout(default, default):Int; public var busy(default, null):Bool; public var completed(default, null):Float; private var url:String; private var method:String; private var data:Null; private var timer:Timer; @:provide private var manager:ILoaderManager; public function new(timeout = 0) { super(); this.timeout = timeout; busy = false; completed = Math.NaN; } public function request(url:String, method:String, data:Dynamic = null):Promise { if (busy) { throwError("Busy"); } else { busy = true; this.url = url; this.method = method; this.data = data; var url:String = this.url; //L.d(TAG, "Request: " + prepareUrl(url)); //internalRequest(prepareUrl(url)); manager.add(this); } return this.promise(); } private function cockTimeout():Void { if (timeout > 0) { timer = new Timer(timeout); timer.run = callTimeout; } } private function cancelTimeout():Void { if (timer != null) { timer.stop(); timer = null; } } public function fromBytes(data:ByteArray):Promise { if (busy) { throwError("Busy"); } else { busy = true; internalFromBytes(data); } return this.promise(); } public function GET(url:String, data:Dynamic = null):Promise { return request(url, URLRequestMethod.GET, data); } public function POST(url:String, data:Dynamic = null):Promise { return request(url, URLRequestMethod.POST, data); } public function DELETE(url:String, data:Dynamic = null):Promise { return request(url, URLRequestMethod.DELETE, data); } private function internalRequest(url:String):Void { throw "Abstract"; } private function internalFromBytes(data:ByteArray):Void { throw "Abstract"; } private function onInit(e:Event):Void {} private function onProgress(e:ProgressEvent):Void { completed = e.bytesLoaded / e.bytesTotal; } private function onComplete(e:Event):Void { var data:T = extrudeResult(e); if (data != null) { resolve(data); } else { throwError("Data is null"); } dispose(); } private function onSecurityError(e:Event):Void { if (proxy == null) { onError(e); } else { cancelTimeout(); internalRequest(proxy(buildUrl())); } } private function onError(e:Event):Void { throwError(e); dispose(); } private function callTimeout():Void { var error:String = "Timeout for: " + url; throwError(error); dispose(); } private function extrudeResult(e:Event):T { throw "Abstract"; return null; } private function dispose():Void { cancelTimeout(); url = null; data = null; busy = false; completed = Math.NaN; manager.release(this); } public function cancel():Void { throwError("Cancelled"); dispose(); } private function buildUrl():String { var u:String = url; if (data != null && method == URLRequestMethod.GET) { var a:Array = []; for (key in Reflect.fields(data)) { a.push(key + "=" + Reflect.field(data, key)); } u += "?" + a.join("&"); } return prepareUrl(u); } public function run():Void { internalRequest(buildUrl()); } }