package java.lang;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import ej.annotation.Nullable;

/**
 * The <code>System</code> class contains several useful class fields and methods. It cannot be
 * instantiated.
 *
 * <p>
 * Among the facilities provided by the <code>System</code> class are standard input, standard
 * output, and error output streams; access to externally defined properties and environment
 * variables; and a utility method for quickly copying a portion of an array.
 */
public final class System {

    /**
     * The "standard" error output stream. This stream is already open and ready to accept output data.
     * <p>
     * Typically this stream corresponds to display output or another output destination specified by
     * the host environment or user. By convention, this output stream is used to display error messages
     * or other information that should come to the immediate attention of a user even if the principal
     * output stream, the value of the variable <code>out</code>, has been redirected to a file or other
     * destination that is typically not continuously monitored.
     */
    public static final PrintStream err = new PrintStream(new OutputStream() {

        @Override
        public void write(int b) throws IOException {
            throw new RuntimeException();
        }
    });

    /**
     * The "standard" output stream. This stream is already open and ready to accept output data.
     * Typically this stream corresponds to display output or another output destination specified by
     * the host environment or user.
     * <p>
     * For simple stand-alone Java applications, a typical way to write a line of output data is:
     * <blockquote>
     *
     * <pre>
     * System.out.println(data)
     * </pre>
     *
     * </blockquote>
     * <p>
     * See the <code>println</code> methods in class <code>PrintStream</code>.
     *
     * @see java.io.PrintStream#println()
     * @see java.io.PrintStream#println(boolean)
     * @see java.io.PrintStream#println(char)
     * @see java.io.PrintStream#println(char[])
     * @see java.io.PrintStream#println(double)
     * @see java.io.PrintStream#println(float)
     * @see java.io.PrintStream#println(int)
     * @see java.io.PrintStream#println(long)
     * @see java.io.PrintStream#println(java.lang.Object)
     * @see java.io.PrintStream#println(java.lang.String)
     */
    public static final PrintStream out = new PrintStream(new OutputStream() {

        @Override
        public void write(int b) throws IOException {
            throw new RuntimeException();
        }
    });

    /**
     * Copies an array from the specified source array, beginning at the specified position, to the
     * specified position of the destination array. A subsequence of array components are copied from
     * the source array referenced by <code>src</code> to the destination array referenced by
     * <code>dest</code>. The number of components copied is equal to the <code>length</code> argument.
     * The components at positions <code>srcPos</code> through <code>srcPos+length-1</code> in the
     * source array are copied into positions <code>destPos</code> through
     * <code>destPos+length-1</code>, respectively, of the destination array.
     * <p>
     * If the <code>src</code> and <code>dest</code> arguments refer to the same array object, then the
     * copying is performed as if the components at positions <code>srcPos</code> through
     * <code>srcPos+length-1</code> were first copied to a temporary array with <code>length</code>
     * components and then the contents of the temporary array were copied into positions
     * <code>destPos</code> through <code>destPos+length-1</code> of the destination array.
     * <p>
     * If <code>dest</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.
     * <p>
     * If <code>src</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown and
     * the destination array is not modified.
     * <p>
     * Otherwise, if any of the following is true, an <code>ArrayStoreException</code> is thrown and the
     * destination is not modified:
     * <ul>
     * <li>The <code>src</code> argument refers to an object that is not an array.
     * <li>The <code>dest</code> argument refers to an object that is not an array.
     * <li>The <code>src</code> argument and <code>dest</code> argument refer to arrays whose component
     * types are different primitive types.
     * <li>The <code>src</code> argument refers to an array with a primitive component type and the
     * <code>dest</code> argument refers to an array with a reference component type.
     * <li>The <code>src</code> argument refers to an array with a reference component type and the
     * <code>dest</code> argument refers to an array with a primitive component type.
     * </ul>
     * <p>
     * Otherwise, if any of the following is true, an <code>IndexOutOfBoundsException</code> is thrown
     * and the destination is not modified:
     * <ul>
     * <li>The <code>srcPos</code> argument is negative.
     * <li>The <code>destPos</code> argument is negative.
     * <li>The <code>length</code> argument is negative.
     * <li><code>srcPos+length</code> is greater than <code>src.length</code>, the length of the source
     * array.
     * <li><code>destPos+length</code> is greater than <code>dest.length</code>, the length of the
     * destination array.
     * </ul>
     * <p>
     * Otherwise, if any actual component of the source array from position <code>srcPos</code> through
     * <code>srcPos+length-1</code> cannot be converted to the component type of the destination array
     * by assignment conversion, an <code>ArrayStoreException</code> is thrown. In this case, let
     * <b><i>k</i></b> be the smallest nonnegative integer less than length such that
     * <code>src[srcPos+</code><i>k</i><code>]</code> cannot be converted to the component type of the
     * destination array; when the exception is thrown, source array components from positions
     * <code>srcPos</code> through <code>srcPos+</code><i>k</i><code>-1</code> will already have been
     * copied to destination array positions <code>destPos</code> through <code>destPos+</code>
     * <i>k</I><code>-1</code> and no other positions of the destination array will have been modified.
     * (Because of the restrictions already itemized, this paragraph effectively applies only to the
     * situation where both arrays have component types that are reference types.)
     *
     * @param src
     *        the source array.
     * @param srcPos
     *        starting position in the source array.
     * @param dest
     *        the destination array.
     * @param destPos
     *        starting position in the destination data.
     * @param length
     *        the number of array elements to be copied.
     * @exception IndexOutOfBoundsException
     *            if copying would cause access of data outside array bounds.
     * @exception ArrayStoreException
     *            if an element in the <code>src</code> array could not be stored into the
     *            <code>dest</code> array because of a type mismatch.
     * @exception NullPointerException
     *            if either <code>src</code> or <code>dest</code> is <code>null</code>.
     */
    public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
        throw new RuntimeException();
    }

    /**
     * Returns the current time in milliseconds. Note that while the unit of time of the return value is
     * a millisecond, the granularity of the value depends on the underlying operating system and may be
     * larger. For example, many operating systems measure time in units of tens of milliseconds.
     *
     * <p>
     * See the description of the class <code>Date</code> for a discussion of slight discrepancies that
     * may arise between "computer time" and coordinated universal time (UTC).
     *
     * @return the difference, measured in milliseconds, between the current time and midnight, January
     *         1, 1970 UTC.
     * @see java.util.Date
     */
    public static long currentTimeMillis() {
        throw new RuntimeException();
    }

    /**
     * Terminates the currently running Java Virtual Machine. The argument serves as a status code; by
     * convention, a nonzero status code indicates abnormal termination.
     * <p>
     * This method calls the <code>exit</code> method in class <code>Runtime</code>. This method never
     * returns normally.
     * <p>
     * The call <code>System.exit(n)</code> is effectively equivalent to the call: <blockquote>
     *
     * <pre>
     * Runtime.getRuntime().exit(n)
     * </pre>
     *
     * </blockquote>
     *
     * @param status
     *        exit status.
     * @throws SecurityException
     *         if a security manager exists and its <code>checkExit</code> method doesn't allow exit
     *         with the specified status.
     * @see java.lang.Runtime#exit(int)
     */
    public static void exit(int status) {
        throw new RuntimeException();
    }

    /**
     * Runs the garbage collector.
     * <p>
     * Calling the <code>gc</code> method suggests that the Java Virtual Machine expend effort toward
     * recycling unused objects in order to make the memory they currently occupy available for quick
     * reuse. When control returns from the method call, the Java Virtual Machine has made a best effort
     * to reclaim space from all discarded objects.
     * <p>
     * The call <code>System.gc()</code> is effectively equivalent to the call: <blockquote>
     *
     * <pre>
     * Runtime.getRuntime().gc()
     * </pre>
     *
     * </blockquote>
     *
     * @see java.lang.Runtime#gc()
     */
    public static void gc() {
        throw new RuntimeException();
    }

    /**
     * Gets the system property indicated by the specified key.
     * <p>
     * First, if there is a security manager, its <code>checkPropertyAccess</code> method is called with
     * the key as its argument. This may result in a SecurityException.
     * <p>
     * If there is no current set of system properties, a set of system properties is first created and
     * initialized in the same manner as for the <code>getProperties</code> method.
     *
     * @param key
     *        the name of the system property.
     * @return the string value of the system property, or <code>null</code> if there is no property
     *         with that key.
     *
     * @exception SecurityException
     *            if a security manager exists and its <code>checkPropertyAccess</code> method doesn't
     *            allow access to the specified system property.
     * @exception NullPointerException
     *            if <code>key</code> is <code>null</code>.
     * @exception IllegalArgumentException
     *            if <code>key</code> is empty.
     * @see java.lang.SecurityException
     */
    @Nullable
    public static String getProperty(String key) {
        throw new RuntimeException();
    }

    /**
     * Gets the system property indicated by the specified key.
     * <p>
     * First, if there is a security manager, its <code>checkPropertyAccess</code> method is called with
     * the <code>key</code> as its argument.
     * <p>
     * If there is no current set of system properties, a set of system properties is first created and
     * initialized in the same manner as for the <code>getProperties</code> method.
     *
     * @param key
     *        the name of the system property.
     * @param def
     *        a default value.
     * @return the string value of the system property, or the default value if there is no property
     *         with that key.
     *
     * @exception SecurityException
     *            if a security manager exists and its <code>checkPropertyAccess</code> method doesn't
     *            allow access to the specified system property.
     * @exception NullPointerException
     *            if <code>key</code> is <code>null</code>.
     * @exception IllegalArgumentException
     *            if <code>key</code> is empty.
     */
    public static String getProperty(String key, String def) {
        throw new RuntimeException();
    }

    /**
     * Gets the system security interface.
     *
     * @return if a security manager has already been established for the current application, then that
     *         security manager is returned; otherwise, <code>null</code> is returned.
     * @see #setSecurityManager
     */
    @Nullable
    public static SecurityManager getSecurityManager() {
        throw new RuntimeException();
    }

    /**
     * Returns the same hash code for the given object as would be returned by the default method
     * hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the
     * null reference is zero.
     *
     * @param x
     *        object for which the hashCode is to be calculated
     * @return the hashCode
     */
    public static int identityHashCode(@Nullable Object x) {
        throw new RuntimeException();
    }

    /**
     * Returns the current value of the running Java Virtual Machine's high-resolution time source, in
     * nanoseconds.
     *
     * <p>
     * This method can only be used to measure elapsed time and is not related to any other notion of
     * system or wall-clock time. The value returned represents nanoseconds since some fixed but
     * arbitrary <i>origin</i> time (perhaps in the future, so values may be negative). The same origin
     * is used by all invocations of this method in an instance of a Java virtual machine; other virtual
     * machine instances are likely to use a different origin.
     *
     * <p>
     * This method provides nanosecond precision, but not necessarily nanosecond resolution (that is,
     * how frequently the value changes) - no guarantees are made except that the resolution is at least
     * as good as that of {@link #currentTimeMillis()}.
     *
     * <p>
     * Differences in successive calls that span greater than approximately 292 years (2<sup>63</sup>
     * nanoseconds) will not correctly compute elapsed time due to numerical overflow.
     *
     * <p>
     * The values returned by this method become meaningful only when the difference between two such
     * values, obtained within the same instance of a Java virtual machine, is computed.
     *
     * <p>
     * For example, to measure how long some code takes to execute:
     *
     * <pre>
     * {
     * 	&#064;code
     * 	long startTime = System.nanoTime();
     * 	// ... the code being measured ...
     * 	long estimatedTime = System.nanoTime() - startTime;
     * }
     * </pre>
     *
     * <p>
     * To compare two nanoTime values
     *
     * <pre>
     * {@code
     * long t0 = System.nanoTime();
     * ...
     * long t1 = System.nanoTime();}
     * </pre>
     *
     * one should use {@code t1 - t0 < 0}, not {@code t1 < t0}, because of the possibility of numerical
     * overflow.
     *
     * @return the current value of the running Java Virtual Machine's high-resolution time source, in
     *         nanoseconds
     */
    public static long nanoTime() {
        throw new RuntimeException();
    }

    /**
     * Sets the System security.
     *
     * <p>
     * If there is a security manager already installed, this method first calls the security manager's
     * <code>checkPermission</code> method with a <code>RuntimePermission("setSecurityManager")</code>
     * permission to ensure it's ok to replace the existing security manager. This may result in
     * throwing a <code>SecurityException</code>.
     *
     * <p>
     * Otherwise, the argument is established as the current security manager. If the argument is
     * <code>null</code> and no security manager has been established, then no action is taken and the
     * method simply returns.
     *
     * @param s
     *        the security manager.
     * @exception SecurityException
     *            if the security manager has already been set and its <code>checkPermission</code>
     *            method doesn't allow it to be replaced.
     * @see #getSecurityManager
     * @see SecurityManager#checkPermission
     * @see java.lang.RuntimePermission
     */
    public static void setSecurityManager(@Nullable SecurityManager s) {
        throw new RuntimeException();
    }
}
