/*
 * Copyright (C) 2017 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.server.telecom.testapps;

import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.role.RoleManager;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.ConnectionRequest;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;

import com.android.server.telecom.testapps.R;

import java.util.Objects;

/**
 * Provides a sample third-party calling app UX which implements the self managed connection service
 * APIs.
 */
public class SelfManagedCallingActivity extends Activity {
    private static final String TAG = "SelfMgCallActivity";
    private static final int REQUEST_ID = 1;
    private SelfManagedCallList mCallList = SelfManagedCallList.getInstance();
    private CheckBox mCheckIfPermittedBeforeCalling;
    private Button mPlaceOutgoingCallButton;
    private Button mPlaceIncomingCallButton;
    private Button mHandoverFrom;
    private Button mRequestCallScreeningRole;
    private RadioButton mUseAcct1Button;
    private RadioButton mUseAcct2Button;
    private CheckBox mHoldableCheckbox;
    private CheckBox mVideoCallCheckbox;
    private EditText mNumber;
    private ListView mListView;
    private TextView mHasFocus;

    private SelfManagedCallListAdapter mListAdapter;

    private SelfManagedCallList.Listener mCallListListener = new SelfManagedCallList.Listener() {
        @Override
        public void onCreateIncomingConnectionFailed(ConnectionRequest request) {
            Log.i(TAG, "onCreateIncomingConnectionFailed " + request);
            Toast.makeText(SelfManagedCallingActivity.this,
                    R.string.incomingCallNotPermittedCS , Toast.LENGTH_SHORT).show();
        };

        @Override
        public void onCreateOutgoingConnectionFailed(ConnectionRequest request) {
            Log.i(TAG, "onCreateOutgoingConnectionFailed " + request);
            Toast.makeText(SelfManagedCallingActivity.this,
                    R.string.outgoingCallNotPermittedCS , Toast.LENGTH_SHORT).show();
        };

        @Override
        public void onConnectionListChanged() {
            Log.i(TAG, "onConnectionListChanged");
            mListAdapter.updateConnections();
        };

        @Override
        public void onConnectionServiceFocusLost() {
            mHasFocus.setText("\uD83D\uDC4E No Focus \uD83D\uDC4E");
        };

        @Override
        public void onConnectionServiceFocusGained() {
            mHasFocus.setText("\uD83D\uDC4D Has Focus \uD83D\uDC4D");
        };
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int flags =
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;

        getWindow().addFlags(flags);
        configureNotificationChannel();
        setContentView(R.layout.self_managed_sample_main);
        mCheckIfPermittedBeforeCalling = (CheckBox) findViewById(
                R.id.checkIfPermittedBeforeCalling);
        mPlaceOutgoingCallButton = (Button) findViewById(R.id.placeOutgoingCallButton);
        mPlaceOutgoingCallButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                placeOutgoingCall();
            }
        });
        mPlaceIncomingCallButton = (Button) findViewById(R.id.placeIncomingCallButton);
        mPlaceIncomingCallButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                placeIncomingCall();
            }
        });
        mHandoverFrom = (Button) findViewById(R.id.handoverFrom);
        mHandoverFrom.setOnClickListener((v -> {
            initiateHandover();
        }));
        mRequestCallScreeningRole = (Button) findViewById(R.id.requestCallScreeningRole);
        mRequestCallScreeningRole.setOnClickListener((v -> {
            requestCallScreeningRole();
        }));

        mUseAcct1Button = findViewById(R.id.useAcct1Button);
        mUseAcct2Button = findViewById(R.id.useAcct2Button);
        mHasFocus = findViewById(R.id.hasFocus);
        mVideoCallCheckbox = findViewById(R.id.videoCall);
        mHoldableCheckbox = findViewById(R.id.holdable);
        mNumber = (EditText) findViewById(R.id.phoneNumber);
        mListView = (ListView) findViewById(R.id.callList);
        mCallList.setListener(mCallListListener);
        mCallList.registerPhoneAccounts(this);
        mListAdapter = new SelfManagedCallListAdapter(getLayoutInflater(),
                mCallList.getConnections());
        mListView.setAdapter(mListAdapter);
        Log.i(TAG, "onCreate - mCallList id " + Objects.hashCode(mCallList));
    }

    private PhoneAccountHandle getSelectedPhoneAccountHandle() {
        if (mUseAcct1Button.isChecked()) {
            return mCallList.getPhoneAccountHandle(SelfManagedCallList.SELF_MANAGED_ACCOUNT_1);
        } else if (mUseAcct2Button.isChecked()) {
            return mCallList.getPhoneAccountHandle(SelfManagedCallList.SELF_MANAGED_ACCOUNT_2);
        }
        return null;
    }

    private void placeOutgoingCall() {
        TelecomManager tm = TelecomManager.from(this);
        PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();

        if (mCheckIfPermittedBeforeCalling.isChecked()) {
            if (!tm.isOutgoingCallPermitted(phoneAccountHandle)) {
                Toast.makeText(this, R.string.outgoingCallNotPermitted , Toast.LENGTH_SHORT).show();
                return;
            }
        }

        Bundle extras = new Bundle();
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                getSelectedPhoneAccountHandle());
        if (mVideoCallCheckbox.isChecked()) {
            extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
                    VideoProfile.STATE_BIDIRECTIONAL);
        }
        Bundle clientExtras = new Bundle();
        clientExtras.putBoolean(SelfManagedConnectionService.EXTRA_HOLDABLE,
                mHoldableCheckbox.isChecked());
        extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, clientExtras);
        tm.placeCall(Uri.parse(mNumber.getText().toString()), extras);
    }

    private void initiateHandover() {
        TelecomManager tm = TelecomManager.from(this);
        PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
        Uri address = Uri.parse(mNumber.getText().toString());
        tm.acceptHandover(address, VideoProfile.STATE_BIDIRECTIONAL, phoneAccountHandle);
    }

    private void placeIncomingCall() {
        TelecomManager tm = TelecomManager.from(this);
        PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();

        if (mCheckIfPermittedBeforeCalling.isChecked()) {
            if (!tm.isIncomingCallPermitted(phoneAccountHandle)) {
                Toast.makeText(this, R.string.incomingCallNotPermitted , Toast.LENGTH_SHORT).show();
                return;
            }
        }

        Bundle extras = new Bundle();
        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                Uri.parse(mNumber.getText().toString()));
        extras.putBoolean(SelfManagedConnectionService.EXTRA_HOLDABLE,
                mHoldableCheckbox.isChecked());
        if (mVideoCallCheckbox.isChecked()) {
            extras.putInt(TelecomManager.EXTRA_INCOMING_VIDEO_STATE,
                    VideoProfile.STATE_BIDIRECTIONAL);
        }
        tm.addNewIncomingCall(getSelectedPhoneAccountHandle(), extras);
    }

    private void configureNotificationChannel() {
        NotificationChannel channel = new NotificationChannel(
                SelfManagedConnection.INCOMING_CALL_CHANNEL_ID, "Incoming Calls",
                NotificationManager.IMPORTANCE_MAX);
        channel.setShowBadge(false);
        Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
        channel.setSound(ringtoneUri, new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .build());
        channel.enableLights(true);

        NotificationManager mgr = getSystemService(NotificationManager.class);
        mgr.createNotificationChannel(channel);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_ID) {
            if (resultCode == android.app.Activity.RESULT_OK) {
                Toast.makeText(this, "Call screening role granted.", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Call screening role NOT granted.", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void requestCallScreeningRole() {
        RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
        Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
        startActivityForResult(intent, REQUEST_ID);
    }
}