import { CanvasGradient } from '../CanvasGradient';
import { Path2D } from '../Path2D';
import { ImageData } from '../ImageData';
import { TextMetrics } from '../TextMetrics';
import { ImageSource, Color } from '@nativescript/core';
import { ImageAsset } from '../../ImageAsset';
import { CanvasPattern } from '../CanvasPattern';
import { Canvas } from '../../Canvas';
import { Helpers } from '../../helpers';
import { DOMMatrix } from '../DOMMatrix';
let ctor;
function ruleToEnum(rule) {
    switch (rule) {
        case 'nonzero':
            return 0;
        case 'evenodd':
            return 1;
        default:
            return -1; // will be ignored
    }
}
function toBaseLine(value) {
    switch (value) {
        case 'top':
            return 0;
        case 'hanging':
            return 1;
        case 'middle':
            return 2;
        case 'alphabetic':
            return 3;
        case 'ideographic':
            return 4;
        case 'bottom':
            return 5;
        default:
            return -1;
    }
}
function fromBaseLine(value) {
    switch (value) {
        case 0:
            return 'top';
        case 1:
            return 'hanging';
        case 2:
            return 'middle';
        case 3:
            return 'alphabetic';
        case 4:
            return 'ideographic';
        case 5:
            return 'bottom';
        default:
            return null;
    }
}
function toBlendMode(value) {
    switch (value) {
        case 'source-over':
            return 0;
        case 'source-in':
            return 1;
        case 'source-out':
            return 2;
        case 'source-atop':
            return 3;
        case 'destination-over':
            return 4;
        case 'destination-in':
            return 5;
        case 'destination-out':
            return 6;
        case 'destination-atop':
            return 7;
        case 'lighter':
            return 8;
        case 'copy':
            return 9;
        case 'xor':
            return 10;
        case 'multiply':
            return 11;
        case 'screen':
            return 12;
        case 'overlay':
            return 13;
        case 'darken':
            return 14;
        case 'lighten':
            return 15;
        case 'color-dodge':
            return 16;
        case 'color-burn':
            return 17;
        case 'hard-light':
            return 18;
        case 'soft-light':
            return 19;
        case 'difference':
            return 20;
        case 'exclusion':
            return 21;
        case 'hue':
            return 22;
        case 'saturation':
            return 23;
        case 'color':
            return 24;
        case 'luminosity':
            return 25;
        default:
            null;
    }
}
function drawNativeImage(args, image, context) {
    let dirty = false;
    const ptr = context.context.__getPointer();
    if (args.length === 3) {
        if (__ANDROID__) {
            dirty = org.nativescript.canvas.NSCCanvasRenderingContext2D.drawImage(long(ptr), image, args[1], args[2]);
        }
        if (__IOS__) {
            dirty = NSCCanvasRenderingContext2D.drawImage(ptr, image, args[1], args[2]);
        }
    }
    else if (args.length === 5) {
        if (__ANDROID__) {
            dirty = org.nativescript.canvas.NSCCanvasRenderingContext2D.drawImage(long(ptr), image, args[1], args[2], args[3], args[4]);
        }
        if (__IOS__) {
            dirty = NSCCanvasRenderingContext2D.drawImage(ptr, image, args[1], args[2], args[3], args[4]);
        }
    }
    else if (args.length === 9) {
        if (__ANDROID__) {
            dirty = org.nativescript.canvas.NSCCanvasRenderingContext2D.drawImage(long(ptr), image, args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
        }
        if (__IOS__) {
            dirty = NSCCanvasRenderingContext2D.drawImage(ptr, image, args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
        }
    }
    if (dirty) {
        context.context.__makeDirty();
    }
}
export class CanvasRenderingContext2D {
    constructor(context, contextOptions) {
        this.contextPtr = context;
        const ctxPtr = BigInt(context.toString());
        this.context = ctor(ctxPtr);
        this._type = '2d';
    }
    get type() {
        return this._type;
    }
    get native() {
        return this.context;
    }
    get canvas() {
        return this._canvas;
    }
    get shadowColor() {
        return this.context.shadowColor;
    }
    set shadowColor(color) {
        this.context.shadowColor = color;
    }
    get font() {
        return this.context.font;
    }
    set font(value) {
        this.context.font = value;
    }
    get direction() {
        return this.context.direction;
    }
    set direction(value) {
        this.context.direction = value;
    }
    get globalAlpha() {
        return this.context.globalAlpha;
    }
    set globalAlpha(alpha) {
        this.context.globalAlpha = alpha;
    }
    get imageSmoothingEnabled() {
        return this.context.imageSmoothingEnabled;
    }
    set imageSmoothingEnabled(enabled) {
        this.context.imageSmoothingEnabled = enabled;
    }
    get imageSmoothingQuality() {
        return this.context.imageSmoothingQuality;
    }
    set imageSmoothingQuality(quality) {
        this.context.imageSmoothingQuality = quality;
    }
    get lineDashOffset() {
        return this.context.lineDashOffset;
    }
    set lineDashOffset(offset) {
        this.context.lineDashOffset = offset;
    }
    get letterSpacing() {
        return this.context.letterSpacing;
    }
    set letterSpacing(spacing) {
        this.context.letterSpacing = spacing;
    }
    get lineJoin() {
        return this.context.lineJoin;
    }
    set lineJoin(join) {
        this.context.lineJoin = join;
    }
    get lineCap() {
        return this.context.lineCap;
    }
    set lineCap(cap) {
        this.context.lineCap = cap;
    }
    get miterLimit() {
        return this.context.miterLimit;
    }
    set miterLimit(limit) {
        this.context.miterLimit = limit;
    }
    get shadowBlur() {
        return this.context.shadowBlur;
    }
    set shadowBlur(blur) {
        this.context.shadowBlur = blur;
    }
    get shadowOffsetX() {
        return this.context.shadowOffsetX;
    }
    set shadowOffsetX(x) {
        this.context.shadowOffsetX = x;
    }
    get shadowOffsetY() {
        return this.context.shadowOffsetY;
    }
    set shadowOffsetY(y) {
        this.context.shadowOffsetY = y;
    }
    get textAlign() {
        return this.context.textAlign;
    }
    set textAlign(alignment) {
        this.context.textAlign = alignment;
    }
    get textBaseline() {
        return fromBaseLine(this.context.textBaseline);
    }
    set textBaseline(baseline) {
        const value = toBaseLine(baseline);
        if (value === -1) {
            return;
        }
        this.context.textBaseline = value;
    }
    get globalCompositeOperation() {
        return this.context.globalCompositeOperation;
    }
    set globalCompositeOperation(composite) {
        this.context.globalCompositeOperation = composite;
    }
    get fillStyle() {
        return this.context.fillStyle;
    }
    set fillStyle(color) {
        if (color === undefined || color === null) {
            return;
        }
        this.context.fillStyle = typeof color === 'object' ? color.native : color;
    }
    get filter() {
        return this.context.filter;
    }
    set filter(value) {
        this.context.filter = value;
    }
    get strokeStyle() {
        return this.context.strokeStyle;
    }
    set strokeStyle(color) {
        if (color === undefined || color === null) {
            return;
        }
        this.context.strokeStyle = typeof color === 'object' ? color.native : color;
    }
    get lineWidth() {
        return this.context.lineWidth;
    }
    set lineWidth(width) {
        this.context.lineWidth = width;
    }
    get wordSpacing() {
        return this.context.wordSpacing;
    }
    set wordSpacing(spacing) {
        this.context.wordSpacing = spacing;
    }
    __toDataURL(type = 'image/jpg', quality = 92) {
        return this.context.__toDataURL(type, quality);
    }
    addHitRegion(region) { }
    arc(x, y, radius, startAngle, endAngle, anticlockwise = false) {
        this.context.arc(x, y, radius, startAngle, endAngle, anticlockwise ?? false);
    }
    arcTo(x1, y1, x2, y2, radius) {
        this.context.arcTo(x1, y1, x2, y2, radius);
    }
    beginPath() {
        this.context.beginPath();
    }
    bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
        this.context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
    }
    clearHitRegions() { }
    clearRect(x, y, width, height) {
        this.context.clearRect(x, y, width, height);
    }
    clip(...args) {
        if (typeof args[0] === 'string') {
            this.context.clip(ruleToEnum(args[0]));
        }
        else if (args[0] instanceof Path2D && typeof args[1] === 'string') {
            this.context.clip(args[0].native, ruleToEnum(args[1]));
        }
        else if (args[0] instanceof Path2D) {
            this.context.clip(args[0].native);
        }
        else {
            this.context.clip();
        }
    }
    closePath() {
        this.context.closePath();
    }
    createImageData(width, height) {
        if (width instanceof ImageData) {
            return new ImageData(width.width, width.height);
        }
        else {
            return new ImageData(width, height);
        }
    }
    createLinearGradient(x0, y0, x1, y1) {
        return CanvasGradient.fromNative(this.context.createLinearGradient(x0, y0, x1, y1));
    }
    createPattern(image, repetition) {
        if (repetition === undefined || typeof repetition !== 'string') {
            const e = new Error('The string did not match the expected pattern.');
            e.name = 'SyntaxError';
            throw e;
        }
        //const createPattern = this._getMethod('createPattern');
        //const createPattern = this.context.createPattern;
        let img;
        if (image?._type === '2d' || image?._type?.indexOf('webgl') > -1) {
            img = image.native;
        }
        else if (image instanceof ImageSource) {
            //const ptr = this.context.__getPointer; //this._getMethod('__getPointer');
            //const createPattern = this.context.__createPatternWithNative; //this._getMethod('__createPatternWithNative');
            if (__ANDROID__) {
                img = image.android;
                const pattern = org.nativescript.canvas.NSCCanvasRenderingContext2D.createPattern(long(this.context.__getPointer()), img, repetition);
                return new CanvasPattern(this.context.__createPatternWithNative(pattern));
            }
            if (__IOS__) {
                img = image.ios;
                const pattern = NSCCanvasRenderingContext2D.createPattern(this.context.__getPointer(), img, repetition);
                return new CanvasPattern(this.context.__createPatternWithNative(pattern));
            }
            return null;
        }
        else if (__ANDROID__ && image instanceof android.graphics.Bitmap) {
            //const ptr = this.context.__getPointer; //this._getMethod('__getPointer');
            const createPattern = this.context.__createPatternWithNative; //this._getMethod('__createPatternWithNative');
            if (__ANDROID__) {
                const pattern = org.nativescript.canvas.NSCCanvasRenderingContext2D.createPattern(long(this.context.__getPointer()), image, repetition);
                return new CanvasPattern(this.context.__createPatternWithNative(pattern));
            }
            if (__IOS__) {
                const pattern = NSCCanvasRenderingContext2D.createPattern(this.context.__getPointer(), image, repetition);
                return new CanvasPattern(this.context.__createPatternWithNative(pattern));
            }
            return null;
        }
        else if (image instanceof ImageAsset) {
            img = image.native;
        }
        else if (image instanceof Canvas) {
            img = image.native;
        }
        else if (image && typeof image.tagName === 'string' && (image.tagName === 'IMG' || image.tagName === 'IMAGE')) {
            if (__ANDROID__ && image._image instanceof android.graphics.Bitmap) {
                //todo ios
                img = image._image;
            }
            else if (image._asset instanceof ImageAsset) {
                img = image._asset.native;
            }
            else if (typeof image.src === 'string') {
                //const ptr = this.context.__getPointer; //this._getMethod('__getPointer');
                //const createPattern = this.context.__createPatternWithNative; //this._getMethod('__createPatternWithNative');
                if (__ANDROID__) {
                    img = ImageSource.fromFileSync(image.src).android;
                    const pattern = org.nativescript.canvas.NSCCanvasRenderingContext2D.createPattern(long(this.context.__getPointer()), img, repetition);
                    return new CanvasPattern(this.context.__createPatternWithNative(pattern));
                }
                if (__IOS__) {
                    img = ImageSource.fromFileSync(image.src).android;
                    const pattern = NSCCanvasRenderingContext2D.createPattern(this.context.__getPointer(), img, repetition);
                    return new CanvasPattern(this.context.__createPatternWithNative(pattern));
                }
                return null;
            }
        }
        else if (image && typeof image.tagName === 'string' && image.tagName === 'CANVAS' && image._canvas instanceof Canvas) {
            img = image._canvas.native;
        }
        else if (image instanceof ImageBitmap) {
            img = image.native;
        }
        if (!img) {
            return null;
        }
        return new CanvasPattern(this.context.createPattern(img, repetition));
    }
    createRadialGradient(x0, y0, r0, x1, y1, r1) {
        return CanvasGradient.fromNative(this.context.createRadialGradient(x0, y0, r0, x1, y1, r1));
    }
    createConicGradient(startAngle, x, y) {
        return CanvasGradient.fromNative(this.context.createConicGradient(startAngle, x, y));
    }
    drawPaint(color) {
        this.context.drawPaint(color);
    }
    drawPoint(x, y) {
        this.context.drawPoint(x, y);
    }
    drawPoints(mode, points) {
        let modeValue = -1;
        switch (mode) {
            case 'points':
                modeValue = 0;
                break;
            case 'lines':
                modeValue = 1;
                break;
            case 'polygon':
                modeValue = 2;
                break;
        }
        this.context.drawPoints(modeValue, points);
    }
    drawFocusIfNeeded(...args) { }
    drawImage(...args) {
        //const drawImage = this.context.drawImage; //this._getMethod('drawImage');
        let image = args[0];
        if (image?._type === '2d' || image?._type?.indexOf('webgl') > -1) {
            image = image.native;
        }
        else if (image instanceof ImageAsset) {
            image = image.native;
        }
        else if (image instanceof ImageSource) {
            if (__ANDROID__) {
                drawNativeImage(args, image.android, this);
            }
            if (__IOS__) {
                drawNativeImage(args, image.ios, this);
            }
            return;
        }
        else if (__ANDROID__ && image instanceof android.graphics.Bitmap) {
            drawNativeImage(args, image, this);
            return;
        }
        else if (__IOS__ && image instanceof UIImage) {
            drawNativeImage(args, image, this);
            return;
        }
        else if (image instanceof Canvas) {
            image = image.native;
        }
        else if (image && typeof image.tagName === 'string' && (image.tagName === 'IMG' || image.tagName === 'IMAGE')) {
            if (image._imageSource instanceof ImageSource) {
                if (__ANDROID__) {
                    drawNativeImage(args, image._imageSource.android, this);
                }
                if (__IOS__) {
                    drawNativeImage(args, image._imageSource.ios, this);
                }
                return;
            }
            else if (__ANDROID__ && image._image instanceof android.graphics.Bitmap) {
                drawNativeImage(args, image._image, this);
                return;
            }
            else if (__ANDROID__ && image._svg) {
                const bitmap = image._svg?._svg?.getBitmap?.();
                if (bitmap) {
                    drawNativeImage(args, bitmap, this);
                }
                return;
            }
            else if (__IOS__ && image._image instanceof UIImage) {
                drawNativeImage(args, image._image, this);
                return;
            }
            else if (image._asset instanceof ImageAsset) {
                image = image._asset.native;
            }
            else if (typeof image.src === 'string') {
                image = ImageSource.fromFileSync(image.src).android;
                if (__ANDROID__) {
                    drawNativeImage(args, image.android, this);
                }
                if (__IOS__) {
                    drawNativeImage(args, image.ios, this);
                }
                return;
            }
        }
        else if (image && typeof image.tagName === 'string' && image.tagName === 'CANVAS' && image._canvas instanceof Canvas) {
            image = image._canvas.native;
        }
        else if (image instanceof ImageBitmap) {
            image = image.native;
        }
        if (args.length === 3) {
            this.context.drawImage(image, args[1], args[2]);
        }
        else if (args.length === 5) {
            this.context.drawImage(image, args[1], args[2], args[3], args[4]);
        }
        else if (args.length === 9) {
            this.context.drawImage(image, args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
        }
    }
    drawAtlas(image, xform, tex, colors, blendMode = 'destination-over') {
        let isNativeSource = false;
        if (image?._type === '2d' || image?._type?.indexOf('webgl') > -1) {
            image = image.native;
        }
        else if (image instanceof ImageAsset) {
            image = image.native;
        }
        else if (image instanceof ImageSource) {
            if (__ANDROID__) {
                isNativeSource = true;
                image = image.android;
            }
            if (__IOS__) {
                isNativeSource = true;
                image = image.ios;
            }
        }
        else if (__ANDROID__ && image instanceof android.graphics.Bitmap) {
            isNativeSource = true;
        }
        else if (__IOS__ && image instanceof UIImage) {
            isNativeSource = true;
        }
        else if (image instanceof Canvas) {
            image = image.native;
        }
        else if (image && typeof image.tagName === 'string' && (image.tagName === 'IMG' || image.tagName === 'IMAGE')) {
            if (image._imageSource instanceof ImageSource) {
                if (__ANDROID__) {
                    isNativeSource = true;
                    image = image._imageSource.android;
                }
                if (__IOS__) {
                    isNativeSource = true;
                    image = image._imageSource.ios;
                }
                return;
            }
            else if (__ANDROID__ && image._image instanceof android.graphics.Bitmap) {
                image = image._image;
                isNativeSource = true;
            }
            else if (__IOS__ && image._image instanceof UIImage) {
                image = image._image;
                isNativeSource = true;
            }
            else if (image._asset instanceof ImageAsset) {
                image = image._asset.native;
            }
            else if (typeof image.src === 'string') {
                image = new ImageAsset();
                image.fromFileSync(image.src);
            }
        }
        else if (image && typeof image.tagName === 'string' && image.tagName === 'CANVAS' && image._canvas instanceof Canvas) {
            image = image._canvas.native;
        }
        else if (image instanceof ImageBitmap) {
            image = image.native;
        }
        if (isNativeSource) {
            if (__IOS__) {
                return;
            }
            if (__ANDROID__) {
                const x = Array.create('float', xform.length * 4);
                let next = 0;
                for (let i = 0; i < xform.length; i++) {
                    const item = xform[i];
                    x[next] = item.scos;
                    x[next + 1] = item.ssin;
                    x[next + 1] = item.tx;
                    x[next + 1] = item.ty;
                    next += 3;
                }
                const t = Array.create('float', tex.length * 4);
                let tnext = 0;
                for (let i = 0; i < tex.length; i++) {
                    const item = tex[i];
                    t[tnext] = item.x;
                    t[tnext + 1] = item.y;
                    t[tnext + 1] = item.width;
                    t[tnext + 1] = item.height;
                    tnext += 3;
                }
                const c = Array.create('int', colors?.length ?? 0);
                if (colors?.length) {
                    for (let i = 0; i < colors.length; i++) {
                        const item = colors[i];
                        c[i] = new Color(item).argb;
                    }
                }
                org.nativescript.canvas.NSCCanvasRenderingContext2D.drawAtlas(this.contextPtr, image, x, t, c, toBlendMode(blendMode ?? 'destination-over') ?? 4);
            }
        }
        else {
            if (image) {
                const x = xform.reduce((accumulator, currentValue) => {
                    accumulator.push(currentValue.scos, currentValue.ssin, currentValue.tx, currentValue.ty);
                    return accumulator;
                }, []);
                const t = tex.reduce((accumulator, currentValue) => {
                    accumulator.push(currentValue.x, currentValue.y, currentValue.width, currentValue.height);
                    return accumulator;
                }, []);
                this.context.drawAtlas(image, x, t, colors ?? null, toBlendMode(blendMode ?? 'destination-over') ?? 4);
            }
        }
    }
    ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise = false) {
        this.context.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise ?? false);
    }
    fill(...args) {
        if (typeof args[0] === 'string') {
            this.context.fill(ruleToEnum(args[0]));
        }
        else if (args[0] instanceof Path2D && typeof args[1] === 'string') {
            this.context.fill(args[0].native, ruleToEnum(args[1]));
        }
        else if (args[0] instanceof Path2D) {
            this.context.fill(args[0].native);
        }
        else {
            this.context.fill();
        }
    }
    fillRect(x, y, width, height) {
        this.context.fillRect(x, y, width, height);
    }
    fillText(text, x, y, maxWidth) {
        if (typeof maxWidth === 'number') {
            this.context.fillText(text + '', x, y, maxWidth);
        }
        else {
            this.context.fillText(text + '', x, y);
        }
    }
    fillOval(x, y, width, height) {
        this.context.fillOval(x, y, width, height);
    }
    getImageData(sx, sy, sw, sh) {
        return ImageData.fromNative(this.context.getImageData(sx, sy, sw, sh));
    }
    getLineDash() {
        return this.context.getLineDash();
    }
    getTransform() {
        return new DOMMatrix(this.context.getTransform());
    }
    isPointInPath(...args) {
        const length = args.length;
        if (length === 2) {
            return this.context.isPointInPath(args[0], args[1]);
        }
        else if (length === 3) {
            return this.context.isPointInPath(args[0], args[1], ruleToEnum(args[2]));
        }
        else if (length === 4 && args[0] instanceof Path2D) {
            return this.context.isPointInPath(args[0].native, args[1], args[2], ruleToEnum(args[3]));
        }
        return false;
    }
    isPointInStroke(...args) {
        const length = args.length;
        if (length === 2) {
            return this.context.isPointInStroke(args[0], args[1]);
        }
        else if (length === 3 && args[0] instanceof Path2D) {
            return this.context.isPointInStroke(args[0].native, args[1], args[2]);
        }
        return false;
    }
    lineTo(x, y) {
        this.context.lineTo(x, y);
    }
    measureText(text) {
        return new TextMetrics(this.context.measureText(text));
    }
    moveTo(x, y) {
        this.context.moveTo(x, y);
    }
    putImageData(...args) {
        if (!args) {
            return;
        }
        const data = args[0];
        const length = args.length;
        if (length === 3) {
            this.context.putImageData(data.native, args[1], args[2]);
        }
        else if (length === 7) {
            this.context.putImageData(data.native, args[1], args[2], args[3], args[4], args[5], args[6]);
        }
    }
    quadraticCurveTo(cpx, cpy, x, y) {
        this.context.quadraticCurveTo(cpx, cpy, x, y);
    }
    rect(x, y, width, height) {
        this.context.rect(x, y, width, height);
    }
    roundRect(x, y, width, height, radii) {
        this.context.roundRect(x, y, width, height, radii);
    }
    removeHitRegion(id) { }
    resetTransform() {
        this.context.resetTransform();
    }
    restore() {
        this.context.restore();
    }
    rotate(angle) {
        this.context.rotate(angle);
    }
    save() {
        this.context.save();
    }
    scale(x, y) {
        this.context.scale(x, y);
    }
    scrollPathIntoView(path) { }
    setLineDash(segments) {
        this.context.setLineDash(segments);
    }
    setTransform(a, b, c, d, e, f) {
        if (typeof a === 'object') {
            // @ts-ignore
            this.context.setTransform(a.native);
        }
        else {
            this.context.setTransform(a, b, c, d, e, f);
        }
    }
    stroke(path) {
        if (path) {
            this.context.stroke(path.native);
        }
        else {
            this.context.stroke();
        }
    }
    strokeRect(x, y, width, height) {
        this.context.strokeRect(x, y, width, height);
    }
    strokeText(text, x, y, maxWidth) {
        if (typeof maxWidth === 'number') {
            this.context.strokeText(text + '', x, y, maxWidth);
        }
        else {
            this.context.strokeText(text + '', x, y);
        }
    }
    strokeOval(x, y, width, height) {
        this.context.strokeOval(x, y, width, height);
    }
    transform(a, b, c, d, e, f) {
        this.context.transform(a, b, c, d, e, f);
    }
    translate(x, y) {
        this.context.translate(x, y);
    }
}
CanvasRenderingContext2D.isDebug = true;
(() => {
    Helpers.initialize();
    //ctor = global.CanvasJSIModule.create2DContext;
    ctor = global.CanvasModule.create2DContextWithPointer;
})();
//# sourceMappingURL=index.js.map