/*
 * Copyright (C) 2014 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.wifi;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.wifi.WifiManager;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.settings.R;
import com.android.settingslib.wifi.AccessPoint;

import java.io.IOException;

class WriteWifiConfigToNfcDialog extends AlertDialog
        implements TextWatcher, View.OnClickListener, CompoundButton.OnCheckedChangeListener {

    private static final String NFC_TOKEN_MIME_TYPE = "application/vnd.wfa.wsc";

    private static final String TAG = WriteWifiConfigToNfcDialog.class.getName().toString();
    private static final String PASSWORD_FORMAT = "102700%s%s";
    private static final int HEX_RADIX = 16;
    private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
    private static final String SECURITY = "security";

    private final PowerManager.WakeLock mWakeLock;

    private View mView;
    private Button mSubmitButton;
    private Button mCancelButton;
    private Handler mOnTextChangedHandler;
    private TextView mPasswordView;
    private TextView mLabelView;
    private CheckBox mPasswordCheckBox;
    private ProgressBar mProgressBar;
    private WifiManagerWrapper mWifiManager;
    private String mWpsNfcConfigurationToken;
    private Context mContext;
    private int mSecurity;

    WriteWifiConfigToNfcDialog(Context context, int security, WifiManagerWrapper wifiManager) {
        super(context);

        mContext = context;
        mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE))
                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WriteWifiConfigToNfcDialog:wakeLock");
        mOnTextChangedHandler = new Handler();
        mSecurity = security;
        mWifiManager = wifiManager;
    }

    WriteWifiConfigToNfcDialog(Context context, Bundle savedState, WifiManagerWrapper wifiManager) {
        super(context);

        mContext = context;
        mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE))
                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WriteWifiConfigToNfcDialog:wakeLock");
        mOnTextChangedHandler = new Handler();
        mSecurity = savedState.getInt(SECURITY);
        mWifiManager = wifiManager;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        mView = getLayoutInflater().inflate(R.layout.write_wifi_config_to_nfc, null);

        setView(mView);
        setInverseBackgroundForced(true);
        setTitle(R.string.setup_wifi_nfc_tag);
        setCancelable(true);
        setButton(DialogInterface.BUTTON_NEUTRAL,
                mContext.getResources().getString(R.string.write_tag), (OnClickListener) null);
        setButton(DialogInterface.BUTTON_NEGATIVE,
                mContext.getResources().getString(com.android.internal.R.string.cancel),
                (OnClickListener) null);

        mPasswordView = mView.findViewById(R.id.password);
        mLabelView = mView.findViewById(R.id.password_label);
        mPasswordView.addTextChangedListener(this);
        mPasswordCheckBox = mView.findViewById(R.id.show_password);
        mPasswordCheckBox.setOnCheckedChangeListener(this);
        mProgressBar = mView.findViewById(R.id.progress_bar);

        super.onCreate(savedInstanceState);

        mSubmitButton = getButton(DialogInterface.BUTTON_NEUTRAL);
        mSubmitButton.setOnClickListener(this);
        mSubmitButton.setEnabled(false);

        mCancelButton = getButton(DialogInterface.BUTTON_NEGATIVE);
    }

    @Override
    public void onClick(View v) {
        mWakeLock.acquire();

        String password = mPasswordView.getText().toString();
        String wpsNfcConfigurationToken = mWifiManager.getCurrentNetworkWpsNfcConfigurationToken();
        String passwordHex = byteArrayToHexString(password.getBytes());

        String passwordLength = password.length() >= HEX_RADIX
                ? Integer.toString(password.length(), HEX_RADIX)
                : "0" + Character.forDigit(password.length(), HEX_RADIX);

        passwordHex = String.format(PASSWORD_FORMAT, passwordLength, passwordHex).toLowerCase();

        if (wpsNfcConfigurationToken != null && wpsNfcConfigurationToken.contains(passwordHex)) {
            mWpsNfcConfigurationToken = wpsNfcConfigurationToken;

            Activity activity = getOwnerActivity();
            NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity);

            nfcAdapter.enableReaderMode(activity, new NfcAdapter.ReaderCallback() {
                @Override
                public void onTagDiscovered(Tag tag) {
                    handleWriteNfcEvent(tag);
                }
            }, NfcAdapter.FLAG_READER_NFC_A |
                    NfcAdapter.FLAG_READER_NFC_B |
                    NfcAdapter.FLAG_READER_NFC_BARCODE |
                    NfcAdapter.FLAG_READER_NFC_F |
                    NfcAdapter.FLAG_READER_NFC_V,
                    null);

            mPasswordView.setVisibility(View.GONE);
            mPasswordCheckBox.setVisibility(View.GONE);
            mSubmitButton.setVisibility(View.GONE);
            InputMethodManager imm = (InputMethodManager)
                    getOwnerActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(mPasswordView.getWindowToken(), 0);

            mLabelView.setText(R.string.status_awaiting_tap);

            mView.findViewById(R.id.password_layout).setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
            mProgressBar.setVisibility(View.VISIBLE);
        } else {
            mLabelView.setText(R.string.status_invalid_password);
        }
    }

    public void saveState(Bundle state) {
        state.putInt(SECURITY, mSecurity);
    }

    private void handleWriteNfcEvent(Tag tag) {
        Ndef ndef = Ndef.get(tag);

        if (ndef != null) {
            if (ndef.isWritable()) {
                NdefRecord record = NdefRecord.createMime(
                        NFC_TOKEN_MIME_TYPE,
                        hexStringToByteArray(mWpsNfcConfigurationToken));
                try {
                    ndef.connect();
                    ndef.writeNdefMessage(new NdefMessage(record));
                    getOwnerActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mProgressBar.setVisibility(View.GONE);
                        }
                    });
                    setViewText(mLabelView, R.string.status_write_success);
                    setViewText(mCancelButton, com.android.internal.R.string.done_label);
                } catch (IOException e) {
                    setViewText(mLabelView, R.string.status_failed_to_write);
                    Log.e(TAG, "Unable to write Wi-Fi config to NFC tag.", e);
                    return;
                } catch (FormatException e) {
                    setViewText(mLabelView, R.string.status_failed_to_write);
                    Log.e(TAG, "Unable to write Wi-Fi config to NFC tag.", e);
                    return;
                }
            } else {
                setViewText(mLabelView, R.string.status_tag_not_writable);
                Log.e(TAG, "Tag is not writable");
            }
        } else {
            setViewText(mLabelView, R.string.status_tag_not_writable);
            Log.e(TAG, "Tag does not support NDEF");
        }
    }

    @Override
    public void dismiss() {
        if (mWakeLock.isHeld()) {
            mWakeLock.release();
        }

        super.dismiss();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        mOnTextChangedHandler.post(new Runnable() {
            @Override
            public void run() {
                enableSubmitIfAppropriate();
            }
        });
    }

    private void enableSubmitIfAppropriate() {

        if (mPasswordView != null) {
            if (mSecurity == AccessPoint.SECURITY_WEP) {
                mSubmitButton.setEnabled(mPasswordView.length() > 0);
            } else if (mSecurity == AccessPoint.SECURITY_PSK) {
                mSubmitButton.setEnabled(mPasswordView.length() >= 8);
            }
        } else {
            mSubmitButton.setEnabled(false);
        }

    }

    private void setViewText(final TextView view, final int resid) {
        getOwnerActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                view.setText(resid);
            }
        });
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        mPasswordView.setInputType(
                InputType.TYPE_CLASS_TEXT |
                (isChecked
                        ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
                        : InputType.TYPE_TEXT_VARIATION_PASSWORD));
    }

    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];

        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), HEX_RADIX) << 4)
                    + Character.digit(s.charAt(i + 1), HEX_RADIX));
        }

        return data;
    }

    private static String byteArrayToHexString(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void afterTextChanged(Editable s) {}
}
