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

class BaseJavaClass
{
    javaClass;
    javaClassName;

    constructor(javaClass)
    {
        this.javaClass = javaClass;

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

    init()
    {
        throw new Error('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;
    }

}

/**
 * A Rectangle specifies an area in a coordinate space that is
 * enclosed by the Rectangle object's upper-left point
 * in the coordinate space, its width, and its height.
 */
class Rectangle
{

    /**
     * The X coordinate of the upper-left corner of the <code>Rectangle</code>.
     */
    x;

    /**
     * The Y coordinate of the upper-left corner of the <code>Rectangle</code>.
     */
    y;

    /**
     * The width of the <code>Rectangle</code>.
     */
    width;

    /**
     * The height of the <code>Rectangle</code>.
     */
    height;

    /**
     * Rectangle constructor.
     * @param x The x-coordinate of the upper-left corner of the rectangle.
     * @param y The y-coordinate of the upper-left corner of the rectangle.
     * @param width The width of the rectangle.
     * @param height The height of the rectangle.
     */
    constructor(x, y, width, height)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    /**
     * Returns the X coordinate of the bounding Rectangle in
     * double precision.
     * @return the X coordinate of the bounding Rectangle.
     */
    getX()
    {
        return this.x;
    }

    /**
     * Returns the Y coordinate of the bounding Rectangle in
     * double precision.
     * @return the Y coordinate of the bounding Rectangle.
     */
    getY()
    {
        return this.y;
    }

    /**
     * Gets the x-coordinate of the left edge of this Rectangle class.
     * @returns The x-coordinate of the left edge of this Rectangle class.
     */
    getLeft()
    {
        return this.getX();
    }

    /**
     * Gets the y-coordinate of the top edge of this Rectangle class.
     * @returns The y-coordinate of the top edge of this Rectangle class.
     */
    getTop()
    {
        return this.getY();
    }

    /**
     * Gets the x-coordinate that is the sum of X and Width property values of this Rectangle class.
     * @returns The x-coordinate that is the sum of X and Width of this Rectangle.
     */
    getRight()
    {
        return this.getX() + this.getWidth();
    }

    /**
     * Gets the y-coordinate that is the sum of the Y and Height property values of this Rectangle class.
     * @returns The y-coordinate that is the sum of Y and Height of this Rectangle.
     */
    getBottom()
    {
        return this.getY() + this.getHeight();
    }

    /**
     * Returns the width of the bounding Rectangle in
     * double precision.
     * @return the width of the bounding Rectangle.
     */
    getWidth()
    {
        return this.width;
    }

    /**
     * Returns the height of the bounding Rectangle in
     * double precision.
     * @return the height of the bounding Rectangle.
     */
    getHeight()
    {
        return this.height;
    }

    toString()
    {
        return this.x + ',' + this.y + ',' + this.width + ',' + this.height;
    }

    /**
     * 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.width <= 0) || (this.height <= 0);
    }
}

class Point
{
    /**
     * The X coordinate.
     */
    x;

    /**
     * The Y coordinate.
     */
    y;

    /**
     * Rectangle constructor.
     * @param x
     * @param y
     */
    constructor(x, y)
    {
        this.x = x;
        this.y = y;
    }

    toString()
    {
        return this.x + ',' + this.y;
    }
}

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
};