/*
 * Copyright (C) 2011 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 com.android.settings.vpn2;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.security.Credentials;
import android.security.KeyStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.google.android.collect.Lists;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class VpnSettings extends SettingsPreferenceFragment implements
        Handler.Callback, Preference.OnPreferenceClickListener,
        DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
    private static final String TAG = "VpnSettings";

    private static final String TAG_LOCKDOWN = "lockdown";

    // TODO: migrate to using DialogFragment when editing

    private final IConnectivityManager mService = IConnectivityManager.Stub
            .asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
    private final KeyStore mKeyStore = KeyStore.getInstance();
    private boolean mUnlocking = false;

    private HashMap<String, VpnPreference> mPreferences = new HashMap<String, VpnPreference>();
    private VpnDialog mDialog;

    private Handler mUpdater;
    private LegacyVpnInfo mInfo;

    // The key of the profile for the current ContextMenu.
    private String mSelectedKey;

    @Override
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        setHasOptionsMenu(true);
        addPreferencesFromResource(R.xml.vpn_settings2);

        if (savedState != null) {
            VpnProfile profile = VpnProfile.decode(savedState.getString("VpnKey"),
                    savedState.getByteArray("VpnProfile"));
            if (profile != null) {
                mDialog = new VpnDialog(getActivity(), this, profile,
                        savedState.getBoolean("VpnEditing"));
            }
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.vpn, menu);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        // Hide lockdown VPN on devices that require IMS authentication
        if (SystemProperties.getBoolean("persist.radio.imsregrequired", false)) {
            menu.findItem(R.id.vpn_lockdown).setVisible(false);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.vpn_create: {
                // Generate a new key. Here we just use the current time.
                long millis = System.currentTimeMillis();
                while (mPreferences.containsKey(Long.toHexString(millis))) {
                    ++millis;
                }
                mDialog = new VpnDialog(
                        getActivity(), this, new VpnProfile(Long.toHexString(millis)), true);
                mDialog.setOnDismissListener(this);
                mDialog.show();
                return true;
            }
            case R.id.vpn_lockdown: {
                LockdownConfigFragment.show(this);
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onSaveInstanceState(Bundle savedState) {
        // We do not save view hierarchy, as they are just profiles.
        if (mDialog != null) {
            VpnProfile profile = mDialog.getProfile();
            savedState.putString("VpnKey", profile.key);
            savedState.putByteArray("VpnProfile", profile.encode());
            savedState.putBoolean("VpnEditing", mDialog.isEditing());
        }
        // else?
    }

    @Override
    public void onResume() {
        super.onResume();

        // Check KeyStore here, so others do not need to deal with it.
        if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
            if (!mUnlocking) {
                // Let us unlock KeyStore. See you later!
                Credentials.getInstance().unlock(getActivity());
            } else {
                // We already tried, but it is still not working!
                finishFragment();
            }
            mUnlocking = !mUnlocking;
            return;
        }

        // Now KeyStore is always unlocked. Reset the flag.
        mUnlocking = false;

        // Currently we are the only user of profiles in KeyStore.
        // Assuming KeyStore and KeyGuard do the right thing, we can
        // safely cache profiles in the memory.
        if (mPreferences.size() == 0) {
            PreferenceGroup group = getPreferenceScreen();

            final Context context = getActivity();
            final List<VpnProfile> profiles = loadVpnProfiles(mKeyStore);
            for (VpnProfile profile : profiles) {
                final VpnPreference pref = new VpnPreference(context, profile);
                pref.setOnPreferenceClickListener(this);
                mPreferences.put(profile.key, pref);
                group.addPreference(pref);
            }
        }

        // Show the dialog if there is one.
        if (mDialog != null) {
            mDialog.setOnDismissListener(this);
            mDialog.show();
        }

        // Start monitoring.
        if (mUpdater == null) {
            mUpdater = new Handler(this);
        }
        mUpdater.sendEmptyMessage(0);

        // Register for context menu. Hmmm, getListView() is hidden?
        registerForContextMenu(getListView());
    }

    @Override
    public void onPause() {
        super.onPause();

        // Hide the dialog if there is one.
        if (mDialog != null) {
            mDialog.setOnDismissListener(null);
            mDialog.dismiss();
        }

        // Unregister for context menu.
        if (getView() != null) {
            unregisterForContextMenu(getListView());
        }
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        // Here is the exit of a dialog.
        mDialog = null;
    }

    @Override
    public void onClick(DialogInterface dialog, int button) {
        if (button == DialogInterface.BUTTON_POSITIVE) {
            // Always save the profile.
            VpnProfile profile = mDialog.getProfile();
            mKeyStore.put(Credentials.VPN + profile.key, profile.encode());

            // Update the preference.
            VpnPreference preference = mPreferences.get(profile.key);
            if (preference != null) {
                disconnect(profile.key);
                preference.update(profile);
            } else {
                preference = new VpnPreference(getActivity(), profile);
                preference.setOnPreferenceClickListener(this);
                mPreferences.put(profile.key, preference);
                getPreferenceScreen().addPreference(preference);
            }

            // If we are not editing, connect!
            if (!mDialog.isEditing()) {
                try {
                    connect(profile);
                } catch (Exception e) {
                    Log.e(TAG, "connect", e);
                }
            }
        }
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
        if (mDialog != null) {
            Log.v(TAG, "onCreateContextMenu() is called when mDialog != null");
            return;
        }

        if (info instanceof AdapterContextMenuInfo) {
            Preference preference = (Preference) getListView().getItemAtPosition(
                    ((AdapterContextMenuInfo) info).position);
            if (preference instanceof VpnPreference) {
                VpnProfile profile = ((VpnPreference) preference).getProfile();
                mSelectedKey = profile.key;
                menu.setHeaderTitle(profile.name);
                menu.add(Menu.NONE, R.string.vpn_menu_edit, 0, R.string.vpn_menu_edit);
                menu.add(Menu.NONE, R.string.vpn_menu_delete, 0, R.string.vpn_menu_delete);
            }
        }
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        if (mDialog != null) {
            Log.v(TAG, "onContextItemSelected() is called when mDialog != null");
            return false;
        }

        VpnPreference preference = mPreferences.get(mSelectedKey);
        if (preference == null) {
            Log.v(TAG, "onContextItemSelected() is called but no preference is found");
            return false;
        }

        switch (item.getItemId()) {
            case R.string.vpn_menu_edit:
                mDialog = new VpnDialog(getActivity(), this, preference.getProfile(), true);
                mDialog.setOnDismissListener(this);
                mDialog.show();
                return true;
            case R.string.vpn_menu_delete:
                disconnect(mSelectedKey);
                getPreferenceScreen().removePreference(preference);
                mPreferences.remove(mSelectedKey);
                mKeyStore.delete(Credentials.VPN + mSelectedKey);
                return true;
        }
        return false;
    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        if (mDialog != null) {
            Log.v(TAG, "onPreferenceClick() is called when mDialog != null");
            return true;
        }

        if (preference instanceof VpnPreference) {
            VpnProfile profile = ((VpnPreference) preference).getProfile();
            if (mInfo != null && profile.key.equals(mInfo.key) &&
                    mInfo.state == LegacyVpnInfo.STATE_CONNECTED) {
                try {
                    mInfo.intent.send();
                    return true;
                } catch (Exception e) {
                    // ignore
                }
            }
            mDialog = new VpnDialog(getActivity(), this, profile, false);
        } else {
            // Generate a new key. Here we just use the current time.
            long millis = System.currentTimeMillis();
            while (mPreferences.containsKey(Long.toHexString(millis))) {
                ++millis;
            }
            mDialog = new VpnDialog(getActivity(), this,
                    new VpnProfile(Long.toHexString(millis)), true);
        }
        mDialog.setOnDismissListener(this);
        mDialog.show();
        return true;
    }

    @Override
    public boolean handleMessage(Message message) {
        mUpdater.removeMessages(0);

        if (isResumed()) {
            try {
                LegacyVpnInfo info = mService.getLegacyVpnInfo();
                if (mInfo != null) {
                    VpnPreference preference = mPreferences.get(mInfo.key);
                    if (preference != null) {
                        preference.update(-1);
                    }
                    mInfo = null;
                }
                if (info != null) {
                    VpnPreference preference = mPreferences.get(info.key);
                    if (preference != null) {
                        preference.update(info.state);
                        mInfo = info;
                    }
                }
            } catch (Exception e) {
                // ignore
            }
            mUpdater.sendEmptyMessageDelayed(0, 1000);
        }
        return true;
    }

    private void connect(VpnProfile profile) throws Exception {
        try {
            mService.startLegacyVpn(profile);
        } catch (IllegalStateException e) {
            Toast.makeText(getActivity(), R.string.vpn_no_network, Toast.LENGTH_LONG).show();
        }
    }

    private void disconnect(String key) {
        if (mInfo != null && key.equals(mInfo.key)) {
            try {
                mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
            } catch (Exception e) {
                // ignore
            }
        }
    }

    @Override
    protected int getHelpResource() {
        return R.string.help_url_vpn;
    }

    private static class VpnPreference extends Preference {
        private VpnProfile mProfile;
        private int mState = -1;

        VpnPreference(Context context, VpnProfile profile) {
            super(context);
            setPersistent(false);
            setOrder(0);

            mProfile = profile;
            update();
        }

        VpnProfile getProfile() {
            return mProfile;
        }

        void update(VpnProfile profile) {
            mProfile = profile;
            update();
        }

        void update(int state) {
            mState = state;
            update();
        }

        void update() {
            if (mState < 0) {
                String[] types = getContext().getResources()
                        .getStringArray(R.array.vpn_types_long);
                setSummary(types[mProfile.type]);
            } else {
                String[] states = getContext().getResources()
                        .getStringArray(R.array.vpn_states);
                setSummary(states[mState]);
            }
            setTitle(mProfile.name);
            notifyHierarchyChanged();
        }

        @Override
        public int compareTo(Preference preference) {
            int result = -1;
            if (preference instanceof VpnPreference) {
                VpnPreference another = (VpnPreference) preference;
                if ((result = another.mState - mState) == 0 &&
                        (result = mProfile.name.compareTo(another.mProfile.name)) == 0 &&
                        (result = mProfile.type - another.mProfile.type) == 0) {
                    result = mProfile.key.compareTo(another.mProfile.key);
                }
            }
            return result;
        }
    }

    /**
     * Dialog to configure always-on VPN.
     */
    public static class LockdownConfigFragment extends DialogFragment {
        private List<VpnProfile> mProfiles;
        private List<CharSequence> mTitles;
        private int mCurrentIndex;

        private static class TitleAdapter extends ArrayAdapter<CharSequence> {
            public TitleAdapter(Context context, List<CharSequence> objects) {
                super(context, com.android.internal.R.layout.select_dialog_singlechoice_holo,
                        android.R.id.text1, objects);
            }
        }

        public static void show(VpnSettings parent) {
            if (!parent.isAdded()) return;

            final LockdownConfigFragment dialog = new LockdownConfigFragment();
            dialog.show(parent.getFragmentManager(), TAG_LOCKDOWN);
        }

        private static String getStringOrNull(KeyStore keyStore, String key) {
            final byte[] value = keyStore.get(Credentials.LOCKDOWN_VPN);
            return value == null ? null : new String(value);
        }

        private void initProfiles(KeyStore keyStore, Resources res) {
            final String lockdownKey = getStringOrNull(keyStore, Credentials.LOCKDOWN_VPN);

            mProfiles = loadVpnProfiles(keyStore, VpnProfile.TYPE_PPTP);
            mTitles = Lists.newArrayList();
            mTitles.add(res.getText(R.string.vpn_lockdown_none));
            mCurrentIndex = 0;

            for (VpnProfile profile : mProfiles) {
                if (TextUtils.equals(profile.key, lockdownKey)) {
                    mCurrentIndex = mTitles.size();
                }
                mTitles.add(profile.name);
            }
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Context context = getActivity();
            final KeyStore keyStore = KeyStore.getInstance();

            initProfiles(keyStore, context.getResources());

            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
            final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());

            builder.setTitle(R.string.vpn_menu_lockdown);

            final View view = dialogInflater.inflate(R.layout.vpn_lockdown_editor, null, false);
            final ListView listView = (ListView) view.findViewById(android.R.id.list);
            listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            listView.setAdapter(new TitleAdapter(context, mTitles));
            listView.setItemChecked(mCurrentIndex, true);
            builder.setView(view);

            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    final int newIndex = listView.getCheckedItemPosition();
                    if (mCurrentIndex == newIndex) return;

                    if (newIndex == 0) {
                        keyStore.delete(Credentials.LOCKDOWN_VPN);

                    } else {
                        final VpnProfile profile = mProfiles.get(newIndex - 1);
                        if (!profile.isValidLockdownProfile()) {
                            Toast.makeText(context, R.string.vpn_lockdown_config_error,
                                    Toast.LENGTH_LONG).show();
                            return;
                        }
                        keyStore.put(Credentials.LOCKDOWN_VPN, profile.key.getBytes());
                    }

                    // kick profiles since we changed them
                    ConnectivityManager.from(getActivity()).updateLockdownVpn();
                }
            });

            return builder.create();
        }
    }

    private static List<VpnProfile> loadVpnProfiles(KeyStore keyStore, int... excludeTypes) {
        final ArrayList<VpnProfile> result = Lists.newArrayList();
        final String[] keys = keyStore.saw(Credentials.VPN);
        if (keys != null) {
            for (String key : keys) {
                final VpnProfile profile = VpnProfile.decode(
                        key, keyStore.get(Credentials.VPN + key));
                if (profile != null && !ArrayUtils.contains(excludeTypes, profile.type)) {
                    result.add(profile);
                }
            }
        }
        return result;
    }
}
