// -*- Mode: java; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-

package com.danger.terminal;

import danger.app.SettingsDB;
import danger.app.SettingsDBException;


class SSHServerInfo
    extends ServerInfo
{
    public 
    SSHServerInfo (SessionManager manager)
    {
        super(manager);
        init();
    }
    
    public
    SSHServerInfo (SessionManager manager, String hostname, String username, int protocol, int port)
    {
        super(manager, hostname, username, port);
        init();
    }
    
    private void
    init()
    {
        mProtocol = ServerInfo.PROT_SSH2;
        mPort = ServerInfo.DEFAULT_PORT[mProtocol];
    }
    
    public byte[]
    getRSAHostKey()
    {
        /* we try again as another session may have saved it */
        if (mRSAHostKey == null) {
            try {
                mRSAHostKey = mPrefs.getBytes(RSA_KEY + "/" + mHostname);
            } catch(SettingsDBException e) { }
        }
        
        return mRSAHostKey;
    }
    
    public void
    setRSAHostKey (byte[] key)
    {
        mRSAHostKey = key;
        if (key == null) {
            mPrefs.remove(RSA_KEY + "/" + mHostname);
        } else {
            mPrefs.setBytes(RSA_KEY + "/" + mHostname, key);
        }
    }
    
    public byte[]
    getDSSHostKey()
    {
        /* we try again as another session may have saved it */
        if (mDSSHostKey == null) {
            try {
                mDSSHostKey = mPrefs.getBytes(DSS_KEY + "/" + mHostname);
            } catch(SettingsDBException e) { }
        }
        
        return mDSSHostKey;
    }
    
    public void
    setDSSHostKey (byte[] key)
    {
        mDSSHostKey = key;
        if (key == null) {
            mPrefs.remove(DSS_KEY + "/" + mHostname);
        } else {
            mPrefs.setBytes(DSS_KEY + "/" + mHostname, key);
        }
    }

    public String
    getProtocolName()
    {
        return Terminal.instance().getString(TerminalResources.PROTOCOL_SSH2);
    }

    public final boolean
    getRememberPassword ()
    {
        return mRememberPassword;
    }

    public final void
    setRememberPassword (boolean remember)
    {
        if (remember != mRememberPassword) {
            mDirty = true;
            mRememberPassword = remember;
        }
    }

    public final boolean
    getPreferDSS ()
    {
        return mPreferDSS;
    }

    public void
    setPreferDSS (boolean preferDSS)
    {
        if (preferDSS != mPreferDSS) {
            mDirty = true;
            mPreferDSS = preferDSS;
        }
    }

    public final int
    getWindowSize ()
    {
        return mWindowSize;
    }

    public void
    setWindowSize (int size)
    {
        if (size != mWindowSize) {
            mDirty = true;
            mWindowSize = size;
        }
    }

    public final String
    getSavedPassword ()
    {
        if (mRememberPassword) {
            return mSavedPassword;
        } else {
            return null;
        }
    }

    public void
    setSavedPassword (String password)
    {
        if ((password == null) || ! password.equals(mSavedPassword)) {
            mDirty = true;
            mSavedPassword = password;
        }
    }
    
    public final String
    getSavedKeyFile ()
    {
        if (mRememberPassword) {
            return mSavedKeyFile;
        } else {
            return null;
        }
    }
    
    public void
    setSavedKeyFile (String keyFile)
    {
        if ((keyFile == null) || ! keyFile.equals(mSavedKeyFile)) {
            mDirty = true;
            mSavedKeyFile = keyFile;
        }
    }

    protected void
    saveTLV (TLVSet tlv)
    {
        super.saveTLV(tlv);
        
        tlv.addBoolean(TLV_REMEMBER_PASSWORD, mRememberPassword);
        tlv.addBoolean(TLV_PREFER_DSS, mPreferDSS);
        tlv.addInt(TLV_WINDOW_SIZE, mWindowSize);

        if ((mSavedPassword == null) || !mRememberPassword) {
            mPrivateDB.remove(PASSWORD_KEY + "/" + mSettingsIndex);
        } else {
            mPrivateDB.setStringValue(PASSWORD_KEY + "/" + mSettingsIndex, mSavedPassword);
        }
        
        if ((mSavedKeyFile == null) || !mRememberPassword) {
            mPrivateDB.remove(KEYFILE_KEY + "/" + mSettingsIndex);
        } else {
            mPrivateDB.setStringValue(KEYFILE_KEY + "/" + mSettingsIndex, mSavedKeyFile);
        }
    }
    
    private void
    loadPrivatePrefs ()
    {
        /* not having keys is a normal thing and so we catch the exception here */
        try {
            mRSAHostKey = mPrefs.getBytes(RSA_KEY + "/" + mHostname);
        } catch (SettingsDBException e) {
            mRSAHostKey = null;
        }

        try {
            mDSSHostKey = mPrefs.getBytes(DSS_KEY + "/" + mHostname);
        } catch (SettingsDBException e) {
            mDSSHostKey = null;
        }

        mSavedPassword = mPrivateDB.getStringValue(PASSWORD_KEY + "/" + mSettingsIndex);
        mSavedKeyFile = mPrivateDB.getStringValue(KEYFILE_KEY + "/" + mSettingsIndex);
    }
    
    protected void
    loadTLV (TLVSet tlv)
    {
        super.loadTLV(tlv);
        
        mRememberPassword = tlv.getBoolean(TLV_REMEMBER_PASSWORD, DEFAULT_REMEMBER_PASSWORD);
        mPreferDSS = tlv.getBoolean(TLV_PREFER_DSS, DEFAULT_PREFER_DSS);
        mWindowSize = tlv.getInt(TLV_WINDOW_SIZE, DEFAULT_WINDOW_SIZE);

        loadPrivatePrefs();
    }
    
    // for old-style prefs; should only be used once, after which the prefs are all converted to TLV format
    protected void
    oldStyleLoadHook ()
        throws SettingsDBException
    {
        mRememberPassword = getBooleanValue(REMEMBER_PASSWORD, DEFAULT_REMEMBER_PASSWORD);
        mPreferDSS = getBooleanValue(PREFER_DSS, DEFAULT_PREFER_DSS);
        mWindowSize = getIntValue(WINDOW_SIZE);

        loadPrivatePrefs();
        
        mPrefs.remove(REMEMBER_PASSWORD + "/" + mSettingsIndex);
        mPrefs.remove(PREFER_DSS + "/" + mSettingsIndex);
        mPrefs.remove(WINDOW_SIZE + "/" + mSettingsIndex);
    }


    // store passwords in a private, non-synced db so we don't send them to the service
    private static SettingsDB mPrivateDB = new SettingsDB("private", false);

    protected boolean                   mRememberPassword = DEFAULT_REMEMBER_PASSWORD;
    protected boolean                   mPreferDSS = DEFAULT_PREFER_DSS;
    protected int                       mWindowSize = DEFAULT_WINDOW_SIZE;
    protected String                    mSavedPassword = null;
    protected String                    mSavedKeyFile = null;
    protected byte[]                    mRSAHostKey = null;
    protected byte[]                    mDSSHostKey = null;

    private static final String         REMEMBER_PASSWORD = "remember-password";
    private static final boolean        DEFAULT_REMEMBER_PASSWORD = false;
    private static final String         PREFER_DSS = "prefer-dss";
    private static final boolean        DEFAULT_PREFER_DSS = false;
    private static final String         WINDOW_SIZE = "window-size";
    private static final int            DEFAULT_WINDOW_SIZE = 8192;
    private static final String         PASSWORD_KEY = "ssh-password";
    private static final String         RSA_KEY = "rsa";
    private static final String         DSS_KEY = "dss";
    private static final String         KEYFILE_KEY = "keyfile";
    
    private static final int            TLV_REMEMBER_PASSWORD = 41;
    private static final int            TLV_PREFER_DSS = 42;
    private static final int            TLV_WINDOW_SIZE = 43;
}
