/*
 * Copyright (C) 2018-2020 Western Digital Corporation or its affiliates 
 * Copyright (C) 2017-2018 Wearable, Inc.
 * Copyright (C) 2000-2012 leJOS Contributors
 * Copyright (C) 2000 Jose H. Solorzano and TinyVM Contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 * 
 * This Source Code Form is “Incompatible With Secondary Licenses”,
 * as defined by the Mozilla Public License, v. 2.0.
 */

package java.lang;

import java.lang.annotation.Annotation;

import org.naniteproject.VM;

/**
 * Not fully functional.
 */
public class Class<T>
{
    @SuppressWarnings("unchecked")
    public <U> Class<? extends U> asSubclass(Class<U> cls)
    {
        if (!cls.isAssignableFrom(this))
            throw new ClassCastException();

        return (Class<? extends U>)this;
    }

    @SuppressWarnings("unchecked")
    public T cast(Object o)
    {
        if (!this.isInstance(o))
            throw new ClassCastException();

        return (T)o;
    }

    /**
     * @exception ClassNotFoundException Thrown always in TinyVM.
     */
    public static Class<?> forName (String aName)
            throws ClassNotFoundException
    {
        throw new ClassNotFoundException();
    }

    public String getName() {
        return "Class " + VM.getClassNumber(this);
    }

  //  @Nullable
    public native Class<?> getComponentType();

    public native Class<? super T> getSuperclass();

    public boolean isAnnotation()
    {
        return this.isInterface() && Annotation.class != this && Annotation.class.isAssignableFrom(this);
    }

    public native boolean isArray();

    public native boolean isAssignableFrom(Class<?> cls);

    public boolean isEnum()
    {
        return this.getSuperclass() == Enum.class;
    }

    public boolean isInstance(Object obj)
    {
        if (obj == null)
            return false;

        return this.isAssignableFrom(obj.getClass());
    }

    public native boolean isInterface();

    public native boolean isPrimitive();

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        if (this.isInterface())
            sb.append("interface ");
        else
            sb.append("class ");

        sb.append(VM.getClassNumber(this));

        return sb.toString();
    }

    public boolean desiredAssertionStatus() { return true; }
}
