/*
---

name: CSSAnimation

license: MIT-style license.

author: Ryan Florence <http://ryanflorence.com>

provides: [CSSAnimation]

...
*/

;(function(global){

var getSupportedStyle = function(element, supported){
for (var i = supported.length - 1; i >= 0; i--){
if (element.style[supported[i]] !== undefined){
return supported[i];
}
};
};

var Transform = global.Transform = function(element, supported){
this.element = element;
this.style = getSupportedStyle(element, supported || [ 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]);
}; global.Transform.prototype = {

translate: function(axis, value){
return this.setter(axis, value, 'translate');
},

rotate: function(axis, value){
if (typeof axis === 'number') return this.add('rotate', axis);
return this.setter(axis, value, 'rotate');
},

skew: function(axis, value){
return this.setter(axis, value, 'skew');
},

scale: function(axis, value){
if (typeof axis === 'number') return this.add('scale', axis);
this.setter(axis, value, 'scale');
return this;
},

matrix: function(){
var transform = this.element.style[this.style],
match = new RegExp(this.rules.matrix.regex).test(transform),
shared = 'matrix(' + Array.prototype.slice.call(arguments, 0).join(',') + ')';
if (transform === 'none') transform = '';
return match
? this.set(transform.replace(this.rules[rule].regex, shared))
: this.set(transform + ' ' + shared);
},

clear: function(){
return this.set('');
},

set: function(def){
this.element.style[this.style] = def;
return this;
},

// not "public", feel free to use, but the rest of these methods
// are not guaranteed to have backward compatibility in future releases

setter: function(a, b, method){
if (typeof a === 'string') return this.add(method + a.toUpperCase(), b);
for (i in a) if (a.hasOwnProperty(i)) this[method](i, a[i])
return this;
},

add: function(rule, value){
var transform = this.element.style[this.style],
rule = rule === 'rotateZ' ? 'rotate' : rule,
match = new RegExp(this.rules[rule].regex).test(transform),
unit = this.rules[rule].unit,
shared = rule + '(' + value + unit + ')';
if (transform === 'none') transform = '';
return match
? this.set(transform.replace(this.rules[rule].regex, shared))
: this.set(transform + ' ' + shared);
},

remove: function(rule){
return this.set(this.element.style[this.style].replace(this.rules[rule].regex, ''));
},

// this is admittadly verbose, but if an API changes,
// this is easy to override and (sortof) future-proof the script
// I'm still not sold it's the right way :\ ... but I'm more interested in
// creating something useful first, then clean it up :D
rules: {
'rotateX':{
regex: /rotateX\((-?[0-9]+deg)\)/,
unit: 'deg'
},
'rotateY': {
regex: /rotateY\((-?[0-9]+deg)\)/,
unit: 'deg'
},
'rotateZ': {
regex:  /rotateZ\((-?[0-9]+deg)\)/,
unit: 'deg'
},
'rotate': {
regex: /rotate\((-?[0-9]+deg)\)/,
unit: 'deg'
},
'translateX': {
regex:  /translateX\((-?[0-9]+%)\)/,
unit: '%'
},
'translateY': {
regex: /translateY\((-?[0-9]+%)\)/,
unit: '%'
},
'translateZ': {
regex: /translateZ\((-?[0-9]+px)\)/,
unit: 'px'
},
'scale': {
regex: /scale\((-?[0-9]+)\)/,
unit: ''
},
'scaleX': {
regex: /scaleX\((-?[0-9]+)\)/,
unit: ''
},
'scaleY': {
regex: /scaleY\((-?[0-9]+)\)/,
unit: ''
},
'skewX': {
regex:  /skewX\((-?[0-9]+deg)\)/,
unit: 'deg'
},
'skewY': {
regex:  /skewY\((-?[0-9]+deg)\)/,
unit: 'deg'
},
'scale': {
regex: /scale\((-?[0-9]+\.?[0-9]+?)\)/,
unit: ''
},
'scaleX': {
regex: /scaleX\((-?[0-9]+\.?[0-9]+?)\)/,
unit: ''
},
'scaleY': {
regex: /scaleY\((-?[0-9]+\.?[0-9]+?)\)/,
unit: ''
},
'matrix': {
regex: /matrix(.+)/,
unit: ''
}
}
};

var Transition = global.Transition = function(element, supported){
this.element = element;
this.supported = supported || {
prefixes:          ['WebkitTransition', 'MozTransition', 'OTransition', 'msTransition' ],
transformPrefixes: ['-webkit-'        , '-moz-'        , '-o-'        , '-ms-']
};
this.style = getSupportedStyle(element, this.supported.prefixes);
this.supported.index = this.supported.prefixes.indexOf(this.style);
}; global.Transition.prototype = {

map: {
'duration': 'Duration',
'property': 'Property',
'timing-function': 'TimingFunction'
},

set: function(property, value){
if (typeof property === 'string') {
if (value === 'transform') value = this.supported.transformPrefixes[this.supported.index] + 'transform';
this.element.style[this.style + this.map[property]] = value;
return this;
}
for (i in property) if (property.hasOwnProperty(i)) this.set(i, property[i]);
return this;
},

clear: function(rule){
if (!rule) {
return this.set({
duration: '',
property: '',
'timing-function': ''
});
}
return this.set(rule, '');
}

}

})(window); // change window to whatever global object you want to hand these constructors from
