/**
 * ObjectIdentifier
 * 
 * An ASN1 type for an ObjectIdentifier
 * We store the oid in an Array.
 * Copyright (c) 2007 Henri Torgemane
 * 
 * See LICENSE.txt for full license information.
 */
package com.hurlant.util.der
{
	import flash.utils.ByteArray;
	
	public class ObjectIdentifier implements IAsn1Type
	{
		private var type:uint;
		private var len:uint;
		private var oid:Array;
		
		public function ObjectIdentifier(type:uint, length:uint, b:*) {
			this.type = type;
			this.len = length;
			if (b is ByteArray) {
				parse(b as ByteArray);
			} else if (b is String) {
				generate(b as String);
			} else {
				throw new Error("Invalid call to new ObjectIdentifier");
			}
		}
		
		private function generate(s:String):void {
			oid = s.split(".");
		}
		
		private function parse(b:ByteArray):void {
			// parse stuff
			// first byte = 40*value1 + value2
			var o:uint = b.readUnsignedByte();
			var a:Array = []
			a.push(uint(o/40));
			a.push(uint(o%40));
			var v:uint = 0;
			while (b.bytesAvailable>0) {
				o = b.readUnsignedByte();
				var last:Boolean = (o&0x80)==0;
				o &= 0x7f;
				v = v*128 + o;
				if (last) {
					a.push(v);
					v = 0;
				}
			}
			oid = a;
		}
		
		public function getLength():uint
		{
			return len;
		}
		
		public function getType():uint
		{
			return type;
		}
		
		public function toDER():ByteArray {
			var tmp:Array = [];
			tmp[0] = oid[0]*40 + oid[1];
			for (var i:int=2;i<oid.length;i++) {
				var v:int = parseInt(oid[i]);
				if (v<128) {
					tmp.push(v);
				} else if (v<128*128) {
					tmp.push( (v>>7)|0x80 );
					tmp.push( v&0x7f );
				} else if (v<128*128*128) {
					tmp.push( (v>>14)|0x80 );
					tmp.push( (v>>7)&0x7f | 0x80 );
					tmp.push( v&0x7f);
				} else if (v<128*128*128*128) {
					tmp.push( (v>>21)|0x80 );
					tmp.push( (v>>14) & 0x7f | 0x80 );
					tmp.push( (v>>7) & 0x7f | 0x80 );
					tmp.push( v & 0x7f );
				} else {
					throw new Error("OID element bigger than we thought. :(");
				}
			}
			len = tmp.length;
			if (type==0) {
				type = 6;
			}
			tmp.unshift(len); // assume length is small enough to fit here.
			tmp.unshift(type);
			var b:ByteArray = new ByteArray;
			for (i=0;i<tmp.length;i++) {
				b[i] = tmp[i];
			}
			return b;
		}

		public function toString():String {
			return DER.indent+oid.join(".");
		}
		
		public function dump():String {
			return "OID["+type+"]["+len+"]["+toString()+"]";
		}
		
	}
}