/**
 * @ignore
 * get cursor position of input
 * @author yiminghe@gmail.com
 */
KISSY.add('combobox/cursor', function (S, Node) {

    var $ = Node.all,
        FAKE_DIV_HTML = "<div style='" +
            "z-index:-9999;" +
            "overflow:hidden;" +
            "position: fixed;" +
            "left:-9999px;" +
            "top:-9999px;" +
            "opacity:0;" +
            // firefox default normal,need to force to use pre-wrap
            "white-space:pre-wrap;" +
            "word-wrap:break-word;" +
            "'></div>",
        FAKE_DIV,
        MARKER = "<span>" +
            // must has content
            // or else <br/><span></span> can not get right coordinates
            "x" +
            "</span>",
        STYLES = [
            'paddingLeft',
            'paddingTop', 'paddingBottom',
            'paddingRight',
            'marginLeft',
            'marginTop',
            'marginBottom',
            'marginRight',
            'borderLeftStyle',
            'borderTopStyle',
            'borderBottomStyle',
            'borderRightStyle',
            'borderLeftWidth',
            'borderTopWidth',
            'borderBottomWidth',
            'borderRightWidth',
            'line-height',
            'outline',
            'height',
            'fontFamily',
            'fontSize',
            'fontWeight',
            'fontVariant',
            'fontStyle'
        ],
        supportInputScrollLeft,
        findSupportInputScrollLeft;

    function getFakeDiv(elem) {
        var fake = FAKE_DIV;
        if (!fake) {
            fake = $(FAKE_DIV_HTML);
        }
        if (String(elem[0].type.toLowerCase()) == 'textarea') {
            fake.css("width", elem.css("width"));
        } else {
            // input does not wrap at all
            fake.css("width", 9999);
        }
        S.each(STYLES, function (s) {
            fake.css(s, elem.css(s));
        });
        if (!FAKE_DIV) {
            fake.insertBefore(elem[0].ownerDocument.body.firstChild);
        }
        FAKE_DIV = fake;
        return fake;
    }

    findSupportInputScrollLeft = function () {
        var doc = document,
            input = $("<input>");
        input.css({
            width: 1,
            position: "absolute",
            left: -9999,
            top: -9999
        });
        input.val("123456789");
        input.appendTo(doc.body);
        input[0].focus();
        supportInputScrollLeft = !!(input[0].scrollLeft > 0);
        input.remove();
        findSupportInputScrollLeft = S.noop;
    };

    // firefox not support, chrome support
    supportInputScrollLeft = false;

    return function (elem) {
        var $elem = $(elem);
        elem = $elem[0];
        var doc = elem.ownerDocument,
            $doc = $(doc),
            elemOffset,
            range,
            fake,
            selectionStart,
            offset,
            marker,
            elemScrollTop = elem.scrollTop,
            elemScrollLeft = elem.scrollLeft;
        if (doc.selection) {
            range = doc.selection.createRange();
            return {
                // http://msdn.microsoft.com/en-us/library/ie/ms533540(v=vs.85).aspx
                // or simple range.offsetLeft for textarea
                left: range.boundingLeft + elemScrollLeft +
                    $doc.scrollLeft(),
                top: range.boundingTop + elemScrollTop +
                    range.boundingHeight + $doc.scrollTop()
            };
        }

        elemOffset = $elem.offset();

        // input does not has scrollLeft
        // so just get the position of the beginning of input
        if (!supportInputScrollLeft && elem.type != 'textarea') {
            elemOffset.top += elem.offsetHeight;
            return elemOffset;
        }

        fake = getFakeDiv($elem);

        selectionStart = elem.selectionStart;

        fake.html(S.escapeHtml(elem.value.substring(0, selectionStart - 1)) +
            // marker
            MARKER);

        // can not set fake to scrollTop,marker is always at bottom of marker
        // when cursor at the middle of textarea , error occurs
        // fake.scrollTop = elemScrollTop;
        // fake.scrollLeft = elemScrollLeft;
        offset = elemOffset;

        // offset.left += 500;
        fake.offset(offset);
        marker = fake.last();
        offset = marker.offset();
        offset.top += marker.height();
        // at the start of textarea , just fetch marker's left
        if (selectionStart > 0) {
            offset.left += marker.width();
        }

        // so minus scrollTop/Left
        offset.top -= elemScrollTop;
        offset.left -= elemScrollLeft;

        // offset.left -= 500;
        return offset;
    };

}, {
    requires: ['node']
});