/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed 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 android.bluetooth;

import java.util.*;

/**
 * An AT (Hayes command) Parser based on (a subset of) the ITU-T V.250 standard.
 * <p>
 *
 * Conformant with the subset of V.250 required for implementation of the
 * Bluetooth Headset and Handsfree Profiles, as per Bluetooth SIP
 * specifications. Also implements some V.250 features not required by
 * Bluetooth - such as chained commands.<p>
 *
 * Command handlers are registered with an AtParser object. These handlers are
 * invoked when command lines are processed by AtParser's process() method.<p>
 *
 * The AtParser object accepts a new command line to parse via its process()
 * method. It breaks each command line into one or more commands. Each command
 * is parsed for name, type, and (optional) arguments, and an appropriate
 * external handler method is called through the AtCommandHandler interface.
 *
 * The command types are<ul>
 * <li>Basic Command. For example "ATDT1234567890". Basic command names are a
 * single character (e.g. "D"), and everything following this character is
 * passed to the handler as a string argument (e.g. "T1234567890").
 * <li>Action Command. For example "AT+CIMI". The command name is "CIMI", and
 * there are no arguments for action commands.
 * <li>Read Command. For example "AT+VGM?". The command name is "VGM", and there
 * are no arguments for get commands.
 * <li>Set Command. For example "AT+VGM=14". The command name is "VGM", and
 * there is a single integer argument in this case. In the general case then
 * can be zero or more arguments (comma delimited) each of integer or string
 * form.
 * <li>Test Command. For example "AT+VGM=?. No arguments.
 * </ul>
 *
 * In V.250 the last four command types are known as Extended Commands, and
 * they are used heavily in Bluetooth.<p>
 *
 * Basic commands cannot be chained in this implementation. For Bluetooth
 * headset/handsfree use this is acceptable, because they only use the basic
 * commands ATA and ATD, which are not allowed to be chained. For general V.250
 * use we would need to improve this class to allow Basic command chaining -
 * however it's tricky to get right because there is no delimiter for Basic
 * command chaining.<p>
 *
 * Extended commands can be chained. For example:<p>
 * AT+VGM?;+VGM=14;+CIMI<p>
 * This is equivalent to:<p>
 * AT+VGM?
 * AT+VGM=14
 * AT+CIMI
 * Except that only one final result code is return (although several
 * intermediate responses may be returned), and as soon as one command in the
 * chain fails the rest are abandoned.<p>
 *
 * Handlers are registered by there command name via register(Char c, ...) or
 * register(String s, ...). Handlers for Basic command should be registered by
 * the basic command character, and handlers for Extended commands should be
 * registered by String.<p>
 *
 * Refer to:<ul>
 * <li>ITU-T Recommendation V.250
 * <li>ETSI TS 127.007  (AT Command set for User Equipment, 3GPP TS 27.007)
 * <li>Bluetooth Headset Profile Spec (K6)
 * <li>Bluetooth Handsfree Profile Spec (HFP 1.5)
 * </ul>
 * @hide
 */
public class AtParser {

    // Extended command type enumeration, only used internally
    private static final int TYPE_ACTION = 0;   // AT+FOO
    private static final int TYPE_READ = 1;     // AT+FOO?
    private static final int TYPE_SET = 2;      // AT+FOO=
    private static final int TYPE_TEST = 3;     // AT+FOO=?

    private HashMap<String, AtCommandHandler> mExtHandlers;
    private HashMap<Character, AtCommandHandler> mBasicHandlers;

    private String mLastInput;  // for "A/" (repeat last command) support

    /**
     * Create a new AtParser.<p>
     * No handlers are registered.
     */
    public AtParser() {
        mBasicHandlers = new HashMap<Character, AtCommandHandler>();
        mExtHandlers = new HashMap<String, AtCommandHandler>();
        mLastInput = "";
    }

    /**
     * Register a Basic command handler.<p>
     * Basic command handlers are later called via their
     * <code>handleBasicCommand(String args)</code> method.
     * @param  command Command name - a single character
     * @param  handler Handler to register
     */
    public void register(Character command, AtCommandHandler handler) {
        mBasicHandlers.put(command, handler);
    }

    /**
     * Register an Extended command handler.<p>
     * Extended command handlers are later called via:<ul>
     * <li><code>handleActionCommand()</code>
     * <li><code>handleGetCommand()</code>
     * <li><code>handleSetCommand()</code>
     * <li><code>handleTestCommand()</code>
     * </ul>
     * Only one method will be called for each command processed.
     * @param  command Command name - can be multiple characters
     * @param  handler Handler to register
     */
    public void register(String command, AtCommandHandler handler) {
        mExtHandlers.put(command, handler);
    }


    /**
     * Strip input of whitespace and force Uppercase - except sections inside
     * quotes. Also fixes unmatched quotes (by appending a quote). Double
     * quotes " are the only quotes allowed by V.250
     */
    static private String clean(String input) {
        StringBuilder out = new StringBuilder(input.length());

        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c == '"') {
                int j = input.indexOf('"', i + 1 );  // search for closing "
                if (j == -1) {  // unmatched ", insert one.
                    out.append(input.substring(i, input.length()));
                    out.append('"');
                    break;
                }
                out.append(input.substring(i, j + 1));
                i = j;
            } else if (c != ' ') {
                out.append(Character.toUpperCase(c));
            }
        }

        return out.toString();
    }

    static private boolean isAtoZ(char c) {
        return (c >= 'A' && c <= 'Z');
    }

    /**
     * Find a character ch, ignoring quoted sections.
     * Return input.length() if not found.
     */
    static private int findChar(char ch, String input, int fromIndex) {
        for (int i = fromIndex; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c == '"') {
                i = input.indexOf('"', i + 1);
                if (i == -1) {
                    return input.length();
                }
            } else if (c == ch) {
                return i;
            }
        }
        return input.length();
    }

    /**
     * Break an argument string into individual arguments (comma delimited).
     * Integer arguments are turned into Integer objects. Otherwise a String
     * object is used.
     */
    static private Object[] generateArgs(String input) {
        int i = 0;
        int j;
        ArrayList<Object> out = new ArrayList<Object>();
        while (i <= input.length()) {
            j = findChar(',', input, i);

            String arg = input.substring(i, j);
            try {
                out.add(new Integer(arg));
            } catch (NumberFormatException e) {
                out.add(arg);
            }

            i = j + 1; // move past comma
        }
        return out.toArray();
    }

    /**
     * Return the index of the end of character after the last character in
     * the extended command name. Uses the V.250 spec for allowed command
     * names.
     */
    static private int findEndExtendedName(String input, int index) {
        for (int i = index; i < input.length(); i++) {
            char c = input.charAt(i);

            // V.250 defines the following chars as legal extended command
            // names
            if (isAtoZ(c)) continue;
            if (c >= '0' && c <= '9') continue;
            switch (c) {
            case '!':
            case '%':
            case '-':
            case '.':
            case '/':
            case ':':
            case '_':
                continue;
            default:
                return i;
            }
        }
        return input.length();
    }

    /**
     * Processes an incoming AT command line.<p>
     * This method will invoke zero or one command handler methods for each
     * command in the command line.<p>
     * @param raw_input The AT input, without EOL delimiter (e.g. <CR>).
     * @return          Result object for this command line. This can be
     *                  converted to a String[] response with toStrings().
     */
    public AtCommandResult process(String raw_input) {
        String input = clean(raw_input);

        // Handle "A/" (repeat previous line)
        if (input.regionMatches(0, "A/", 0, 2)) {
            input = new String(mLastInput);
        } else {
            mLastInput = new String(input);
        }

        // Handle empty line - no response necessary
        if (input.equals("")) {
            // Return []
            return new AtCommandResult(AtCommandResult.UNSOLICITED);
        }

        // Anything else deserves an error
        if (!input.regionMatches(0, "AT", 0, 2)) {
            // Return ["ERROR"]
            return new AtCommandResult(AtCommandResult.ERROR);
        }

        // Ok we have a command that starts with AT. Process it
        int index = 2;
        AtCommandResult result =
                new AtCommandResult(AtCommandResult.UNSOLICITED);
        while (index < input.length()) {
            char c = input.charAt(index);

            if (isAtoZ(c)) {
                // Option 1: Basic Command
                // Pass the rest of the line as is to the handler. Do not
                // look for any more commands on this line.
                String args = input.substring(index + 1);
                if (mBasicHandlers.containsKey((Character)c)) {
                    result.addResult(mBasicHandlers.get(
                            (Character)c).handleBasicCommand(args));
                    return result;
                } else {
                    // no handler
                    result.addResult(
                            new AtCommandResult(AtCommandResult.ERROR));
                    return result;
                }
                // control never reaches here
            }

            if (c == '+') {
                // Option 2: Extended Command
                // Search for first non-name character. Short-circuit if
                // we don't handle this command name.
                int i = findEndExtendedName(input, index + 1);
                String commandName = input.substring(index, i);
                if (!mExtHandlers.containsKey(commandName)) {
                    // no handler
                    result.addResult(
                            new AtCommandResult(AtCommandResult.ERROR));
                    return result;
                }
                AtCommandHandler handler = mExtHandlers.get(commandName);

                // Search for end of this command - this is usually the end of
                // line
                int endIndex = findChar(';', input, index);

                // Determine what type of command this is.
                // Default to TYPE_ACTION if we can't find anything else
                // obvious.
                int type;

                if (i >= endIndex) {
                    type = TYPE_ACTION;
                } else if (input.charAt(i) == '?') {
                    type = TYPE_READ;
                } else if (input.charAt(i) == '=') {
                    if (i + 1 < endIndex) {
                        if (input.charAt(i + 1) == '?') {
                            type = TYPE_TEST;
                        } else {
                            type = TYPE_SET;
                        }
                    } else {
                        type = TYPE_SET;
                    }
                } else {
                    type = TYPE_ACTION;
                }

                // Call this command. Short-circuit as soon as a command fails
                switch (type) {
                case TYPE_ACTION:
                    result.addResult(handler.handleActionCommand());
                    break;
                case TYPE_READ:
                    result.addResult(handler.handleReadCommand());
                    break;
                case TYPE_TEST:
                    result.addResult(handler.handleTestCommand());
                    break;
                case TYPE_SET:
                    Object[] args =
                            generateArgs(input.substring(i + 1, endIndex));
                    result.addResult(handler.handleSetCommand(args));
                    break;
                }
                if (result.getResultCode() != AtCommandResult.OK) {
                    return result;   // short-circuit
                }

                index = endIndex;
            } else {
                // Can't tell if this is a basic or extended command.
                // Push forwards and hope we hit something.
                index++;
            }
        }
        // Finished processing (and all results were ok)
        return result;
    }
}
