/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.pos.adaptor;

import java.awt.Component;
import java.awt.Container;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilProperties;


/**
 * KeyboardAdaptor - Handles reading keyboard input
 *
 */
public class KeyboardAdaptor {

    public static final String module = KeyboardAdaptor.class.getName();

    public static final int EVENT_RELEASED = 2;
    public static final int EVENT_PRESSED = 1;
    public static final int EVENT_TYPED = 3;

    public static final int KEYBOARD_DATA = 100;
    public static final int SCANNER_DATA = 101;
    public static final int MSR_DATA = 102;
    public static final int ALL_DATA = 999;

    protected static List<Component> loadedComponents = new LinkedList<Component>();
    protected static Map<KeyboardReceiver, Integer> receivers = new LinkedHashMap<KeyboardReceiver, Integer>();
    protected static KeyboardAdaptor adaptor = null;
    protected static boolean running = true;

    protected KeyboardListener listener = null;

    public static KeyboardAdaptor getInstance(KeyboardReceiver receiver, int dataType) {
        if (adaptor == null) {
            synchronized(KeyboardAdaptor.class) {
                if (adaptor == null) {
                    adaptor = new KeyboardAdaptor();
                }
            }
        }

        if (receiver != null && dataType > -1) {
            receivers.put(receiver, dataType);
        }
        return adaptor;
    }

    public static KeyboardAdaptor getInstance() {
        return getInstance(null, -1);
    }

    public static void attachComponents(Component[] coms, boolean recurse) {
        // check the adaptor
        if (adaptor == null) {
            KeyboardAdaptor.getInstance();
        }

        // add the new ones to listen on
        if (adaptor != null && coms != null) {
            adaptor.addComponents(coms, recurse);
        }
    }

    public static void attachComponents(Component[] coms) {
        KeyboardAdaptor.attachComponents(coms, true);
    }

    public static void attachComponents(Container parent, boolean recurse) {
        KeyboardAdaptor.attachComponents(new Component[] { parent }, recurse);
    }

    public static void attachComponents(Container parent) {
        KeyboardAdaptor.attachComponents(parent, true);
    }

    public static void stop() {
        running = false;
    }

    private KeyboardAdaptor() {
        this.listener = new KeyboardListener();
        this.listener.setDaemon(false);
        this.listener.setName(listener.toString());
        this.listener.start();
        KeyboardAdaptor.adaptor = this;
    }

    private void addComponents(Component[] coms, boolean recurse) {
        listener.reader.configureComponents(coms, recurse);
    }

    private class KeyboardListener extends Thread {

        public final Long MAX_WAIT_SCANNER = new Long(Long.parseLong(UtilProperties.getPropertyValue("jpos.properties", "MaxWaitScanner", "100")));
        public final Long MAX_WAIT_KEYBOARD = new Long(Long.parseLong(UtilProperties.getPropertyValue("jpos.properties", "MaxWaitKeyboard", "10")));
        // By default keyboard entry (login & password 1st)
        public Long MAX_WAIT = MAX_WAIT_KEYBOARD;

        private List<Integer> keyCodeData = new LinkedList<Integer>();
        private List<Character> keyCharData = new LinkedList<Character>();
        private long lastKey = -1;
        private KeyReader reader = null;

        public KeyboardListener() {
            this.reader = new KeyReader(this);
        }

        private int checkDataType(char[] chars) {
            if (chars.length == 0) {
                // non-character data from keyboard interface (i.e. FN keys, enter, esc, etc)
                return KEYBOARD_DATA;
            } else if ((chars[0]) == 2 && (chars[chars.length - 1]) == 10) {
                // test for scanner data
                return SCANNER_DATA;
            } else if ((chars[0]) == 37 && (chars[chars.length - 1]) == 10) {
                // test for MSR data
                return MSR_DATA;
            } else {
                // otherwise it's keyboard data
                return KEYBOARD_DATA;
            }
        }

        protected synchronized void receiveCode(int keycode) {
            keyCodeData.add(keycode);
        }

        protected synchronized void receiveChar(char keychar) {
            keyCharData.add(new Character(keychar));
            if (keychar == '\2') {
                MAX_WAIT = MAX_WAIT_SCANNER;
            }
        }

        protected synchronized void sendData() {
            if (KeyboardAdaptor.receivers.size() > 0) {
                if (keyCharData.size() > 0 || keyCodeData.size() > 0) {
                    char[] chars = new char[keyCharData.size()];
                    int[] codes = new int[keyCodeData.size()];

                    for (int i = 0; i < codes.length; i++) {
                        Integer itg = keyCodeData.get(i);
                        codes[i] = itg.intValue();
                    }

                    for (int i = 0; i < chars.length; i++) {
                        Character ch = keyCharData.get(i);
                        chars[i] = ch.charValue();
                    }

                    for (KeyboardReceiver receiver : receivers.keySet()) {
                        int receiverType = (receivers.get(receiver)).intValue();
                        int thisDataType = this.checkDataType(chars);
                        if (receiverType == ALL_DATA || receiverType == thisDataType) {
                            receiver.receiveData(codes, chars);
                        }
                    }

                    keyCharData = new LinkedList<Character>();
                    keyCodeData = new LinkedList<Integer>();
                    lastKey = -1;
                    MAX_WAIT = MAX_WAIT_KEYBOARD;
                }
            } else {
                Debug.logWarning("No receivers configured for key input", module);
            }
        }

        protected synchronized void sendEvent(int eventType, KeyEvent event) {
            lastKey = System.currentTimeMillis();
            if (KeyboardAdaptor.receivers.size() > 0) {
                for (KeyboardReceiver receiver : KeyboardAdaptor.receivers.keySet()) {
                    if (receiver instanceof KeyListener) {
                        switch (eventType) {
                            case 1:
                                ((KeyListener) receiver).keyPressed(event);
                                break;
                            case 2:
                                ((KeyListener) receiver).keyTyped(event);
                                break;
                            case 3:
                                ((KeyListener) receiver).keyReleased(event);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }

        @Override
        public void run() {
            while (running) {
                long now = System.currentTimeMillis();
                if ((lastKey > -1) && (now - lastKey) >= MAX_WAIT.intValue()) {
                    this.sendData();
                }

                if (!running) {
                    break;
                } else {
                    try {
                        Thread.sleep(MAX_WAIT.intValue());
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }

    class KeyReader implements KeyListener {

        private KeyboardListener k;

        public KeyReader(KeyboardListener k) {
            this.k = k;
        }

        private void configureComponents(Component[] coms, boolean recurse) {
            for (int i = 0; i < coms.length; i++) {
                if (!loadedComponents.contains(coms[i])) {
                    coms[i].addKeyListener(this);
                    Debug.logInfo("Added [" + coms[i].getName() + "] to KeyboardAdaptor", module);
                }
                if (recurse && coms[i] instanceof Container) {
                    Component[] nextComs = ((Container) coms[i]).getComponents();
                    configureComponents(nextComs, true);
                }
            }
        }

        public void keyTyped(KeyEvent e) {
            k.receiveChar(e.getKeyChar());
            k.sendEvent(EVENT_TYPED, e);
        }

        public void keyPressed(KeyEvent e) {
            k.receiveCode(e.getKeyCode());
            k.sendEvent(EVENT_PRESSED, e);
        }

        public void keyReleased(KeyEvent e) {
            k.sendEvent(EVENT_RELEASED, e);
        }
    }
}
