// 
// Decompiled by Procyon v0.6.0
// 

package org.fusesource.jansi.internal;

import java.io.UnsupportedEncodingException;
import java.io.IOException;

public class Kernel32
{
    public static short FOREGROUND_BLUE;
    public static short FOREGROUND_GREEN;
    public static short FOREGROUND_RED;
    public static short FOREGROUND_INTENSITY;
    public static short BACKGROUND_BLUE;
    public static short BACKGROUND_GREEN;
    public static short BACKGROUND_RED;
    public static short BACKGROUND_INTENSITY;
    public static short COMMON_LVB_LEADING_BYTE;
    public static short COMMON_LVB_TRAILING_BYTE;
    public static short COMMON_LVB_GRID_HORIZONTAL;
    public static short COMMON_LVB_GRID_LVERTICAL;
    public static short COMMON_LVB_GRID_RVERTICAL;
    public static short COMMON_LVB_REVERSE_VIDEO;
    public static short COMMON_LVB_UNDERSCORE;
    public static int FORMAT_MESSAGE_FROM_SYSTEM;
    public static int STD_INPUT_HANDLE;
    public static int STD_OUTPUT_HANDLE;
    public static int STD_ERROR_HANDLE;
    public static int INVALID_HANDLE_VALUE;
    
    private static native void init();
    
    public static native long malloc(final long p0);
    
    public static native void free(final long p0);
    
    public static native int SetConsoleTextAttribute(final long p0, final short p1);
    
    public static native int WaitForSingleObject(final long p0, final int p1);
    
    public static native int CloseHandle(final long p0);
    
    public static native int GetLastError();
    
    public static native int FormatMessageW(final int p0, final long p1, final int p2, final int p3, final byte[] p4, final int p5, final long[] p6);
    
    public static native int GetConsoleScreenBufferInfo(final long p0, final CONSOLE_SCREEN_BUFFER_INFO p1);
    
    public static native long GetStdHandle(final int p0);
    
    public static native int SetConsoleCursorPosition(final long p0, final COORD p1);
    
    public static native int FillConsoleOutputCharacterW(final long p0, final char p1, final int p2, final COORD p3, final int[] p4);
    
    public static native int FillConsoleOutputAttribute(final long p0, final short p1, final int p2, final COORD p3, final int[] p4);
    
    public static native int WriteConsoleW(final long p0, final char[] p1, final int p2, final int[] p3, final long p4);
    
    public static native int GetConsoleMode(final long p0, final int[] p1);
    
    public static native int SetConsoleMode(final long p0, final int p1);
    
    public static native int _getch();
    
    public static native int SetConsoleTitle(final String p0);
    
    public static native int GetConsoleOutputCP();
    
    public static native int SetConsoleOutputCP(final int p0);
    
    public static native int ScrollConsoleScreenBuffer(final long p0, final SMALL_RECT p1, final SMALL_RECT p2, final COORD p3, final CHAR_INFO p4);
    
    private static native int ReadConsoleInputW(final long p0, final long p1, final int p2, final int[] p3);
    
    private static native int PeekConsoleInputW(final long p0, final long p1, final int p2, final int[] p3);
    
    public static native int GetNumberOfConsoleInputEvents(final long p0, final int[] p1);
    
    public static native int FlushConsoleInputBuffer(final long p0);
    
    public static INPUT_RECORD[] readConsoleInputHelper(final long handle, final int count, final boolean peek) throws IOException {
        final int[] length = { 0 };
        long inputRecordPtr = 0L;
        try {
            inputRecordPtr = malloc(INPUT_RECORD.SIZEOF * count);
            if (inputRecordPtr == 0L) {
                throw new IOException("cannot allocate memory with JNI");
            }
            final int res = peek ? PeekConsoleInputW(handle, inputRecordPtr, count, length) : ReadConsoleInputW(handle, inputRecordPtr, count, length);
            if (res == 0) {
                throw new IOException("ReadConsoleInputW failed: " + getLastErrorMessage());
            }
            if (length[0] <= 0) {
                return new INPUT_RECORD[0];
            }
            final INPUT_RECORD[] records = new INPUT_RECORD[length[0]];
            for (int i = 0; i < records.length; ++i) {
                INPUT_RECORD.memmove(records[i] = new INPUT_RECORD(), inputRecordPtr + i * INPUT_RECORD.SIZEOF, INPUT_RECORD.SIZEOF);
            }
            return records;
        }
        finally {
            if (inputRecordPtr != 0L) {
                free(inputRecordPtr);
            }
        }
    }
    
    public static INPUT_RECORD[] readConsoleKeyInput(final long handle, final int count, final boolean peek) throws IOException {
        INPUT_RECORD[] evts;
        int keyEvtCount;
        do {
            evts = readConsoleInputHelper(handle, count, peek);
            keyEvtCount = 0;
            for (final INPUT_RECORD evt : evts) {
                if (evt.eventType == INPUT_RECORD.KEY_EVENT) {
                    ++keyEvtCount;
                }
            }
        } while (keyEvtCount <= 0);
        final INPUT_RECORD[] res = new INPUT_RECORD[keyEvtCount];
        int i = 0;
        for (final INPUT_RECORD evt2 : evts) {
            if (evt2.eventType == INPUT_RECORD.KEY_EVENT) {
                res[i++] = evt2;
            }
        }
        return res;
    }
    
    public static String getLastErrorMessage() {
        final int errorCode = GetLastError();
        return getErrorMessage(errorCode);
    }
    
    public static String getErrorMessage(final int errorCode) {
        final int bufferSize = 160;
        final byte[] data = new byte[bufferSize];
        FormatMessageW(Kernel32.FORMAT_MESSAGE_FROM_SYSTEM, 0L, errorCode, 0, data, bufferSize, null);
        try {
            return new String(data, "UTF-16LE").trim();
        }
        catch (final UnsupportedEncodingException e) {
            throw new IllegalStateException(e);
        }
    }
    
    static {
        if (JansiLoader.initialize()) {
            init();
        }
    }
    
    public static class SMALL_RECT
    {
        public static int SIZEOF;
        public short left;
        public short top;
        public short right;
        public short bottom;
        
        private static native void init();
        
        public short width() {
            return (short)(this.right - this.left);
        }
        
        public short height() {
            return (short)(this.bottom - this.top);
        }
        
        public SMALL_RECT copy() {
            final SMALL_RECT rc = new SMALL_RECT();
            rc.left = this.left;
            rc.top = this.top;
            rc.right = this.right;
            rc.bottom = this.bottom;
            return rc;
        }
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class COORD
    {
        public static int SIZEOF;
        public short x;
        public short y;
        
        private static native void init();
        
        public COORD copy() {
            final COORD rc = new COORD();
            rc.x = this.x;
            rc.y = this.y;
            return rc;
        }
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class CONSOLE_SCREEN_BUFFER_INFO
    {
        public static int SIZEOF;
        public COORD size;
        public COORD cursorPosition;
        public short attributes;
        public SMALL_RECT window;
        public COORD maximumWindowSize;
        
        public CONSOLE_SCREEN_BUFFER_INFO() {
            this.size = new COORD();
            this.cursorPosition = new COORD();
            this.window = new SMALL_RECT();
            this.maximumWindowSize = new COORD();
        }
        
        private static native void init();
        
        public int windowWidth() {
            return this.window.width() + 1;
        }
        
        public int windowHeight() {
            return this.window.height() + 1;
        }
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class CHAR_INFO
    {
        public static int SIZEOF;
        public short attributes;
        public char unicodeChar;
        
        private static native void init();
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class KEY_EVENT_RECORD
    {
        public static int SIZEOF;
        public static int CAPSLOCK_ON;
        public static int NUMLOCK_ON;
        public static int SCROLLLOCK_ON;
        public static int ENHANCED_KEY;
        public static int LEFT_ALT_PRESSED;
        public static int LEFT_CTRL_PRESSED;
        public static int RIGHT_ALT_PRESSED;
        public static int RIGHT_CTRL_PRESSED;
        public static int SHIFT_PRESSED;
        public boolean keyDown;
        public short repeatCount;
        public short keyCode;
        public short scanCode;
        public char uchar;
        public int controlKeyState;
        
        private static native void init();
        
        @Override
        public String toString() {
            return "KEY_EVENT_RECORD{keyDown=" + this.keyDown + ", repeatCount=" + this.repeatCount + ", keyCode=" + this.keyCode + ", scanCode=" + this.scanCode + ", uchar=" + this.uchar + ", controlKeyState=" + this.controlKeyState + '}';
        }
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class MOUSE_EVENT_RECORD
    {
        public static int SIZEOF;
        public static int FROM_LEFT_1ST_BUTTON_PRESSED;
        public static int FROM_LEFT_2ND_BUTTON_PRESSED;
        public static int FROM_LEFT_3RD_BUTTON_PRESSED;
        public static int FROM_LEFT_4TH_BUTTON_PRESSED;
        public static int RIGHTMOST_BUTTON_PRESSED;
        public static int CAPSLOCK_ON;
        public static int NUMLOCK_ON;
        public static int SCROLLLOCK_ON;
        public static int ENHANCED_KEY;
        public static int LEFT_ALT_PRESSED;
        public static int LEFT_CTRL_PRESSED;
        public static int RIGHT_ALT_PRESSED;
        public static int RIGHT_CTRL_PRESSED;
        public static int SHIFT_PRESSED;
        public static int DOUBLE_CLICK;
        public static int MOUSE_HWHEELED;
        public static int MOUSE_MOVED;
        public static int MOUSE_WHEELED;
        public COORD mousePosition;
        public int buttonState;
        public int controlKeyState;
        public int eventFlags;
        
        public MOUSE_EVENT_RECORD() {
            this.mousePosition = new COORD();
        }
        
        private static native void init();
        
        @Override
        public String toString() {
            return "MOUSE_EVENT_RECORD{mousePosition=" + this.mousePosition + ", buttonState=" + this.buttonState + ", controlKeyState=" + this.controlKeyState + ", eventFlags=" + this.eventFlags + '}';
        }
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class WINDOW_BUFFER_SIZE_RECORD
    {
        public static int SIZEOF;
        public COORD size;
        
        public WINDOW_BUFFER_SIZE_RECORD() {
            this.size = new COORD();
        }
        
        private static native void init();
        
        @Override
        public String toString() {
            return "WINDOW_BUFFER_SIZE_RECORD{size=" + this.size + '}';
        }
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class FOCUS_EVENT_RECORD
    {
        public static int SIZEOF;
        public boolean setFocus;
        
        private static native void init();
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class MENU_EVENT_RECORD
    {
        public static int SIZEOF;
        public int commandId;
        
        private static native void init();
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
    
    public static class INPUT_RECORD
    {
        public static int SIZEOF;
        public static short KEY_EVENT;
        public static short MOUSE_EVENT;
        public static short WINDOW_BUFFER_SIZE_EVENT;
        public static short FOCUS_EVENT;
        public static short MENU_EVENT;
        public short eventType;
        public KEY_EVENT_RECORD keyEvent;
        public MOUSE_EVENT_RECORD mouseEvent;
        public WINDOW_BUFFER_SIZE_RECORD windowBufferSizeEvent;
        public MENU_EVENT_RECORD menuEvent;
        public FOCUS_EVENT_RECORD focusEvent;
        
        public INPUT_RECORD() {
            this.keyEvent = new KEY_EVENT_RECORD();
            this.mouseEvent = new MOUSE_EVENT_RECORD();
            this.windowBufferSizeEvent = new WINDOW_BUFFER_SIZE_RECORD();
            this.menuEvent = new MENU_EVENT_RECORD();
            this.focusEvent = new FOCUS_EVENT_RECORD();
        }
        
        private static native void init();
        
        public static native void memmove(final INPUT_RECORD p0, final long p1, final long p2);
        
        static {
            JansiLoader.initialize();
            init();
        }
    }
}
