/*
 * @(#)TelnetOption.java
 *
 * Copyright (c) 2001-2002 JScape
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JScape. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JScape.
 */
package com.jscape.inet.telnet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * TelnetOption class enables developers to implement and use existing and
 * future telnet protocol options. The framework is specified in RFC 855 and
 * standard options are specified in separate RFC documents.<br>
 * <p>
 * <b>Notes for subclassing:</b><br>
 * For some options (i.e. ECHO or BINARY), it is enough to pass an option code
 * to the constructor to be able to use it. Many options, however, use
 * subnegotiation and the TelnetOption class should be subclassed. For those
 * options requiring subnegotiation the option class should set <code>optionCode</code>
 * in constructor and override methods <code>readSubnegotation</code> and
 * <code>writeSubnegotiation</code> for formatting/parsing option specific data.
 * </p>
 */
public class TelnetOption
        implements Cloneable {

    /**
     * The unique option code specified in option RFC for this TelnetOption.
     */
    protected int optionCode = -1;

    /**
     * Stores an array of option names.  Each option name may be retrieved by using its corresponding
     * option code as the index in the array to retrieve.
     */
    private static final String[] OPTION_MAP = new String[256];

    static {
        OPTION_MAP[0] = new String("BINARY"); // RFC 856
        OPTION_MAP[1] = new String("ECHO"); // RFC 857
        OPTION_MAP[3] = new String("SUPPRESS_GO_AHEAD"); // RFC 858
        OPTION_MAP[5] = new String("STATUS"); // RFC 859
        OPTION_MAP[6] = new String("TIMING_MARK"); // RFC 860
        OPTION_MAP[7] = new String("RCTE");
        // RFC 726   Remote Controlled Transmission and Echoing Telnet Option
        OPTION_MAP[17] = new String("EXTEND_ASCII"); // RFC 698
        OPTION_MAP[18] = new String("LOGOUT"); // RFC 727
        OPTION_MAP[19] = new String("BM[BYTE_MACRO]"); // RFC 735
        OPTION_MAP[21] = new String("SUPDUP"); // RFC 736
        OPTION_MAP[22] = new String("SUPDUP_OUTPUT"); // RFC 749
        OPTION_MAP[23] = new String("SEND_LOCATION"); // RFC 779
        OPTION_MAP[24] = new String("TERMINAL_TYPE"); // RFC 1091
        OPTION_MAP[25] = new String("END_OF_RECORD"); // RFC 885
        OPTION_MAP[26] = new String("TUID");
        // RFC 927   Tacacs user identification
        OPTION_MAP[27] = new String("OUTMARK"); // RFC 933   Output mark
        OPTION_MAP[28] = new String("TTYLOC");
        // RFC 946   Telnet terminal location
        OPTION_MAP[29] = new String("3270_REGIME"); // RFC 1041
        OPTION_MAP[30] = new String("X.3_PAD"); // RFC 1053
        OPTION_MAP[31] = new String("NAWS");
        // RFC 1073  Negotiate about window size
        OPTION_MAP[32] = new String("TERMINAL_SPEED"); // RFC 1079
        OPTION_MAP[33] = new String("TOGGLE_FLOW_CONTROL"); // RFC 1372
        OPTION_MAP[34] = new String("LINEMODE"); // RFC 1184
        OPTION_MAP[35] = new String("X_DISPLAY_LOCATION"); // RFC 1096
        OPTION_MAP[36] = new String("ENVIRON"); // RFC 1408
        OPTION_MAP[37] = new String("AUTHENTICATION"); // RFC 2941
        OPTION_MAP[39] = new String("NEW_ENVIRON"); // RFC 1572
    }

    /**
     * Creates a new TelnetOption instance.
     * Empty constructor does nothing.  To be used for subclassing new TelnetOption.
     */
    protected TelnetOption() {
    }

    /**
     * Creates a new TelnetOption instance.
     * <p/>
     * The optionCode parameter identifies the option code for this Telnet option.  For a list
     * of valid option codes please consult the Telnet RFCs.  Some examples of valid option codes
     * include the following:
     * <p>
     * 0 - BINARY<br>
     * Negotiates transmission of binary data<br>
     * 1 - ECHO<br>
     * Negotiates echoing of data exchanged<br>
     * 24 - TERMINAL TYPE<br>
     * Negotiates terminal display options<br>
     * </p>
     *
     * @param optionCode the option code
     */
    public TelnetOption(int optionCode) {
        this.optionCode = optionCode;
    }

    /**
     * Gets option code.
     *
     * @return option code
     */
    public int getOptionCode() {
        return optionCode;
    }

    /**
     * Writes subnegotiation data for this TelnetOption.
     * By default this method is empty and and is intended for use in subclasses requiring
     * option negotiation.
     *
     * @param out the OutputStream to write data to.
     *
     * @throws IOException if an I/O related error occurs.
     */
    public void writeSubnegotiation(OutputStream out)
            throws IOException {
    }

    /**
     * Reads subnegotiation data for this TelnetOption
     * By default this method is empty and and is intended for use in subclasses requiring
     * option negotiation.
     *
     * @param in the InputStream to read from
     *
     * @throws IOException if an I/O related error occurs
     */
    public void readSubnegotiation(InputStream in)
            throws IOException {
    }

    /**
     * Gets name of this option based on its option code.
     *
     * @return option name or null if name cannot be found
     */
    public String getOptionName() {
        return OPTION_MAP[optionCode];
    }
}
