/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
import { AUTO_STYLE, BaseException } from '@angular/core';
import { StringMapWrapper } from '../facade/collection';
import { StringWrapper, isNumber, isPresent } from '../facade/lang';
import { getDOM } from './dom_adapter';
import { dashCaseToCamelCase } from './util';
import { WebAnimationsPlayer } from './web_animations_player';
export class WebAnimationsDriver {
    animate(element, startingStyles, keyframes, duration, delay, easing) {
        var anyElm = element;
        var formattedSteps = [];
        var startingStyleLookup = {};
        if (isPresent(startingStyles) && startingStyles.styles.length > 0) {
            startingStyleLookup = _populateStyles(anyElm, startingStyles, {});
            startingStyleLookup['offset'] = 0;
            formattedSteps.push(startingStyleLookup);
        }
        keyframes.forEach((keyframe) => {
            let data = _populateStyles(anyElm, keyframe.styles, startingStyleLookup);
            data['offset'] = keyframe.offset;
            formattedSteps.push(data);
        });
        // this is a special case when only styles are applied as an
        // animation. When this occurs we want to animate from start to
        // end with the same values. Removing the offset and having only
        // start/end values is suitable enough for the web-animations API
        if (formattedSteps.length == 1) {
            var start = formattedSteps[0];
            start['offset'] = null;
            formattedSteps = [start, start];
        }
        var playerOptions = {
            'duration': duration,
            'delay': delay,
            'easing': easing,
            'fill': 'both' // we use `both` because it allows for styling at 0% to work with `delay`
        };
        var player = this._triggerWebAnimation(anyElm, formattedSteps, playerOptions);
        return new WebAnimationsPlayer(player, duration);
    }
    /** @internal */
    _triggerWebAnimation(elm, keyframes, options) {
        return elm.animate(keyframes, options);
    }
}
function _populateStyles(element, styles, defaultStyles) {
    var data = {};
    styles.styles.forEach((entry) => {
        StringMapWrapper.forEach(entry, (val, prop) => {
            var formattedProp = dashCaseToCamelCase(prop);
            data[formattedProp] = val == AUTO_STYLE ?
                _computeStyle(element, formattedProp) :
                val.toString() + _resolveStyleUnit(val, prop, formattedProp);
        });
    });
    StringMapWrapper.forEach(defaultStyles, (value, prop) => {
        if (!isPresent(data[prop])) {
            data[prop] = value;
        }
    });
    return data;
}
function _resolveStyleUnit(val, userProvidedProp, formattedProp) {
    var unit = '';
    if (_isPixelDimensionStyle(formattedProp) && val != 0 && val != '0') {
        if (isNumber(val)) {
            unit = 'px';
        }
        else if (_findDimensionalSuffix(val.toString()).length == 0) {
            throw new BaseException('Please provide a CSS unit value for ' + userProvidedProp + ':' + val);
        }
    }
    return unit;
}
const _$0 = 48;
const _$9 = 57;
const _$PERIOD = 46;
function _findDimensionalSuffix(value) {
    for (var i = 0; i < value.length; i++) {
        var c = StringWrapper.charCodeAt(value, i);
        if ((c >= _$0 && c <= _$9) || c == _$PERIOD)
            continue;
        return value.substring(i, value.length);
    }
    return '';
}
function _isPixelDimensionStyle(prop) {
    switch (prop) {
        case 'width':
        case 'height':
        case 'minWidth':
        case 'minHeight':
        case 'maxWidth':
        case 'maxHeight':
        case 'left':
        case 'top':
        case 'bottom':
        case 'right':
        case 'fontSize':
        case 'outlineWidth':
        case 'outlineOffset':
        case 'paddingTop':
        case 'paddingLeft':
        case 'paddingBottom':
        case 'paddingRight':
        case 'marginTop':
        case 'marginLeft':
        case 'marginBottom':
        case 'marginRight':
        case 'borderRadius':
        case 'borderWidth':
        case 'borderTopWidth':
        case 'borderLeftWidth':
        case 'borderRightWidth':
        case 'borderBottomWidth':
        case 'textIndent':
            return true;
        default:
            return false;
    }
}
function _computeStyle(element, prop) {
    return getDOM().getComputedStyle(element)[prop];
}
//# sourceMappingURL=web_animations_driver.js.map