const java = require('java');
const fs = require("fs");


function isPath(image)
{
    if (image.length < 256 && image.includes("/") || image.includes("\\"))
    {
        if (fs.existsSync(image))
        {
            return true;
        }
        throw new joint.BarcodeException("Path " + image + " does not exist");
    }
    return false;
}

function convertResourceToBase64String(resource)
{
    let is_path_to_image = false;
    is_path_to_image = fs.existsSync(resource);

    if (is_path_to_image)
    {
        return fs.readFileSync(resource).toString('base64');
    }
    else
    {
        return resource;
    }
}

class BaseJavaClass
{
    javaClass;
    javaClassName;

    constructor(javaClass)
    {
        this.javaClass = javaClass;

        if (this.javaClassName == null || this.javaClassName === "")
        {
            this.javaClassName = this.javaClass.__signature;
        }
    }

    init()
    {
        throw new BarcodeException('You have to implement the method init!');
    }

    /**
     * @return mixed
     */
    getJavaClass()
    {
        return this.javaClass;
    }

    /**
     * @return mixed
     */
    setJavaClass(javaClass)
    {
        this.javaClass = javaClass;
        this.init();
    }

    getJavaClassName()
    {
        return this.javaClassName;
    }

    isNull()
    {
        return java_cast(this.javaClass.isNull(), "boolean");
    }

    printJavaClassName()
    {
        console.log("Java class name => '" + this.javaClassName + "'");
    }
}

/**
 * Provides methods to license the component.
 */
class License extends BaseJavaClass
{
    static get javaClassName()
    {
        return "com.aspose.nodejs.barcode.license.NodejsLicense"
    };

    /**
     * Initializes a new instance of this class.
     */
    constructor()
    {
        let javaLicense = java.import(License.javaClassName);
        super(new javaLicense());
    }

    /**
     * Licenses the component.
     *
     * @param licenseName Can be a full or short file name
     */
    setLicense(filePath)
    {
        try
        {
            let file_data = License.openFile(filePath);
            this.getJavaClass().setLicenseSync(file_data);
        } catch (ex)
        {
            throw new BarcodeException(ex);
        }
    }

    isLicensed()
    {
        let is_licensed = this.getJavaClass().isLicensedSync();
        return is_licensed.toString();
    }

    static openFile(filename)
    {
        let buffer = Buffer.from(fs.readFileSync(filename, 'utf8'));
        let array = [];
        array.push('');
        for (let i = 0; i < buffer.length; i++)
        {
            array.push(buffer[i] + '');
        }
        return array;
    }

    init()
    {
//      do nothing
    }
}

/**
 * Class BarcodeException
 */
class BarcodeException extends Error
{
    static get MAX_LINES()
    {
        return 4;
    };

    /**
     * BarcodeException constructor.
     * @param  exc exception's instance
     */
    constructor(exc)
    {
        super();
        if ((typeof exc.toString()) === 'string')
        {
            this.setMessage(exc.toString());
            return;
        }
        let exc_message = "Exception occured in file:line" + nl;

        this.setMessage(exc_message);
    }

    getDetails(exc)
    {
        let details = "";
        if (typeof exc === 'string' || exc instanceof String)
        {
            return exc;
        }
        if (get_class(exc) != null)
        {
            details = "exception type : " + get_class(exc) + "\n";
        }
        if (method_exists(exc, "__toString"))
        {
            details += exc.__toString();
        }
        if (method_exists(exc, "getMessage"))
        {
            details += exc.getMessage();
        }
        if (method_exists(exc, "getCause"))
        {
            details += exc.getCause();
        }
        return details;
    }

    /**
     * @param mixed message
     */
    setMessage(message)
    {
        this.message = message;
    }

}

class Rectangle extends BaseJavaClass
{

    static get EMPTY()
    {
        return new Rectangle(0, 0,0,0);
    }

    init()
    {
        // TODO: Implement init() method.
    }

    static get javaClassName()
    {
        return "java.awt.Rectangle";
    }

    /**
     * Rectangle constructor.
     * @param x
     * @param y
     * @param width
     * @param height
     */
    constructor(x, y, width, height)
    {
        let java_class_link = java.import(Rectangle.javaClassName);
        let java_class = new java_class_link(x, y, width, height);
        super(java_class);
    }

    static construct(...args)
    {
        let rectangle = this.EMPTY;
        rectangle.setJavaClass(args[0]);
        return rectangle;
    }

    getX()
    {
        return this.getJavaClass().getXSync();
    }

    getY()
    {
        return this.getJavaClass().getYSync();
    }

    getLeft()
    {
        return this.getX();
    }

    getTop()
    {
        return this.getY();
    }

    getRight()
    {
        return this.getX() + this.getWidth();
    }

    getBottom()
    {
        return this.getY() + this.getHeight();
    }

    getWidth()
    {
        return this.getJavaClass().getWidthSync();
    }

    getHeight()
    {
        return this.getJavaClass().getHeightSync();
    }

    toString()
    {
        return this.getX() + ',' + this.getY() + ',' + this.getWidth() + ',' + this.getHeight();
    }

    equals(obj)
    {
        return this.getJavaClass().equals(obj.getJavaClass());
    }

    /**
     * Determines if this rectangle intersects with rect.
     * @param rectangle
     * @returns {boolean}
     */
    intersectsWithInclusive(rectangle)
    {
        return !((this.getLeft() > rectangle.getRight()) || (this.getRight() < rectangle.getLeft()) ||
            (this.getTop() > rectangle.getBottom()) || (this.getBottom() < rectangle.getTop()));
    }

    /**
     * Intersect Shared Method
     * Produces a new Rectangle by intersecting 2 existing
     * Rectangles. Returns null if there is no    intersection.
     */
    static intersect(a, b)
    {
        if (!a.intersectsWithInclusive(b))
        {
            return new Rectangle(0, 0, 0, 0);
        }
        return Rectangle.fromLTRB(Math.max(a.getLeft(), b.getLeft()),
            Math.max(a.getTop(), b.getTop()),
            Math.min(a.getRight(), b.getRight()),
            Math.min(a.getBottom(), b.getBottom()));
    }

    /**
     * FromLTRB Shared Method
     * Produces a Rectangle class from left, top, right,
     * and bottom coordinates.
     */
    static fromLTRB(left, top, right, bottom)
    {
        return new Rectangle(left, top, right - left, bottom - top);
    }

    isEmpty()
    {
        return (this.getWidth() <= 0) || (this.getHeight() <= 0);
    }
}

class Point extends BaseJavaClass
{
    static get javaClassName()
    {
        return "java.awt.Point";
    }

    /**
     * Represents a Quadrangle structure with its properties left uninitialized.Value: Quadrangle
     */
    static get EMPTY()
    {
        return new Point(0, 0);
    }

    /**
     * Rectangle constructor.
     * @param x
     * @param y
     */
    constructor(x, y)
    {
        let java_class_link = java.import(Point.javaClassName);
        let java_class = new java_class_link(x, y);
        super(java_class);
    }

    static construct(...args)
    {
        let point = Point.EMPTY;
        point.setJavaClass(args[0]);
        return point;
    }

    init()
    {
        // TODO: Implement init() method.
    }

    getX()
    {
        return this.getJavaClass().getXSync();
    }

    getY()
    {
        return this.getJavaClass().getYSync();
    }

    setX(x)
    {
        this.getJavaClass().xSync = x;
    }

    setY(y)
    {
        this.getJavaClass().ySync = y;
    }

    toString()
    {
        return this.getX() + ',' + this.getY();
    }

    equals(obj)
    {
        return this.getJavaClass().equals(obj.getJavaClass());
    }
}

class BuildVersionInfo
{
    static get javaClassName()
    {
        return "com.aspose.barcode.BuildVersionInfo";
    }

    static get javaClass()
    {
        let java_class_link = java.import(BuildVersionInfo.javaClassName);
        return java_class_link;
    }

    static get product()
    {
        return BuildVersionInfo.javaClass.PRODUCT;
    }

    static get assemblyVersion()
    {
        return BuildVersionInfo.javaClass.ASSEMBLY_VERSION;
    }

}

module.exports = {
    BaseJavaClass, BarcodeException, Rectangle, Point, License, BuildVersionInfo, isPath, convertResourceToBase64String
};