package keris.lang;

import java.lang.reflect.*;


public module SYSTEM {
    
    /** copy array s
     */
    public Object[] arraycopy(Object[] s) {
        if (s == null)
            return null;
        Object[] res = (Object[])Array.newInstance(
            s.getClass().getComponentType(), s.length);
        System.arraycopy(s, 0, res, 0, s.length);
        return res;
    }
    
    /** copy array s into new array of length len
     */
    public Object[] arraycopy(Object[] s, int len) {
        Object[] res = (Object[])Array.newInstance(
            s.getClass().getComponentType(), len);
        System.arraycopy(s, 0, res, 0, s.length);
        return res;
    }
    
    /** copy array s into new array of length len at offset dpos
     */
    public Object[] arraycopy(Object[] s, int dpos, int len) {
        Object[] res = (Object[])Array.newInstance(
            s.getClass().getComponentType(), len);
        System.arraycopy(s, 0, res, dpos, s.length);
        return res;
    }
    
    /** copy array s into array d
     */
    public void arraycopy(Object[] s, Object[] d) {
        System.arraycopy(s, 0, d, 0, s.length);
    }
    
    /** copy array s from offset sp with length len into array d
     *  starting at offset dp
     */
    public void arraycopy(Object[] s, int sp, Object[] d, int dp, int len) {
        System.arraycopy(s, sp, d, dp, len);
    }
    
    /** prepend object a to array as
     */
    public Object[] arrayappend(Object a, Object[] bs) {
        Object[] res = (Object[])Array.newInstance(
            bs.getClass().getComponentType(), bs.length + 1);
        System.arraycopy(bs, 0, res, 1, res.length);
        res[0] = a;
        return res;
    }
    
    /** append object a to array as
     */
    public Object[] arrayappend(Object[] bs, Object a) {
        Object[] res = (Object[])Array.newInstance(
            bs.getClass().getComponentType(), bs.length + 1);
        System.arraycopy(bs, 0, res, 0, res.length);
        res[bs.length] = a;
        return res;
    }
    
    /** append arrays as and bs
     */
    public Object[] arrayappend(Object[] cs, Object[] bs) {
        if (cs == null)
            return bs;
        if (bs == null)
            return cs;
        Object[] res = (Object[])Array.newInstance(
            cs.getClass().getComponentType(), cs.length + bs.length);
        System.arraycopy(cs, 0, res, 0, cs.length);
        System.arraycopy(bs, 0, res, cs.length, bs.length);
        return res;
    }
    
    /** return the current time
     */
    public long currentTimeMillis() {
        return System.currentTimeMillis();
    }
    
    /** simple stop watch
     */
    private long[] stopWatchStart = new long[4];
    private int stopWatches = 0;
    
    public void startTimer() {
        if (stopWatchStart.length == stopWatches) {
            long[] res = new long[stopWatches * 2];
            System.arraycopy(stopWatchStart, 0, res, 0, stopWatches);
            stopWatchStart = res;
        }
        stopWatchStart[stopWatches++] = System.currentTimeMillis();
    }
    
    public long stopTimer() {
        return System.currentTimeMillis() - stopWatchStart[--stopWatches];
    }
    
    /** the original hash code
     */
    public int identityHashCode(Object x) {
        return System.identityHashCode(x);
    }
    
    /** exit the program
     */
    public void exit() {
        System.exit(0);
    }
    
    public void exit(int i) {
        System.exit(i);
    }
    
    /** propose to run the garbage collector
     */
    public void gc() {
        System.gc();
    }
}
