package com.lemenzo.messenger;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.lemenzo.messenger.data.BroadcastStore;
import com.lemenzo.messenger.model.BroadcastRecord;
import com.lemenzo.messenger.sms.SmsSender;
import com.lemenzo.messenger.sms.SubscriptionHelper;
import com.lemenzo.messenger.ui.Ui;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public final class BroadcastActivity extends Activity {
    public static final String EXTRA_BROADCAST_ID = "broadcast_id";

    private BroadcastStore store;
    private String id;
    private TextView headerName;
    private TextView headerSubtitle;
    private ScrollView scroll;
    private LinearLayout history;
    private EditText input;
    private ImageButton send;
    private boolean sendInFlight;
    private final ExecutorService sendExecutor = Executors.newSingleThreadExecutor();

    private final SharedPreferences.OnSharedPreferenceChangeListener listener =
            (prefs,key) -> {
                if (key != null && key.equals("record." + id)) {
                    runOnUiThread(this::render);
                }
            };

    @Override public void onCreate(Bundle state) {
        super.onCreate(state);
        id=getIntent().getStringExtra(EXTRA_BROADCAST_ID);
        store=new BroadcastStore(this);
        build();
        render();
    }

    @Override protected void onResume(){
        super.onResume();
        store.preferences().registerOnSharedPreferenceChangeListener(listener);
        render();
    }

    @Override protected void onPause(){
        store.preferences().unregisterOnSharedPreferenceChangeListener(listener);
        super.onPause();
    }

    @Override protected void onDestroy(){
        sendExecutor.shutdown();
        super.onDestroy();
    }

    private void build(){
        LinearLayout root=new LinearLayout(this);
        root.setOrientation(LinearLayout.VERTICAL);
        root.setBackgroundColor(getColor(R.color.lemenzo_background));
        root.setPadding(Ui.dp(root,14),Ui.dp(root,6),Ui.dp(root,14),Ui.dp(root,8));
        Ui.applyImeAwareInsets(this,root);

        LinearLayout header=new LinearLayout(this);
        header.setGravity(Gravity.CENTER_VERTICAL);
        header.setPadding(0,Ui.dp(root,4),0,Ui.dp(root,8));

        ImageButton back=Ui.iconButton(this,R.drawable.ic_back,getString(R.string.navigate_back));
        back.setOnClickListener(v->finish());
        header.addView(back,new LinearLayout.LayoutParams(Ui.dp(root,48),Ui.dp(root,52)));

        LinearLayout identity=new LinearLayout(this);
        identity.setOrientation(LinearLayout.VERTICAL);
        identity.setPadding(Ui.dp(root,10),0,Ui.dp(root,4),0);

        headerName=Ui.text(this,"",17.5f,true);
        headerName.setSingleLine(true);
        identity.addView(headerName);

        headerSubtitle=Ui.text(this,"",11.5f,false);
        headerSubtitle.setTextColor(getColor(R.color.lemenzo_text_muted));
        headerSubtitle.setSingleLine(true);
        identity.addView(headerSubtitle);

        header.addView(identity,new LinearLayout.LayoutParams(0,-2,1f));
        root.addView(header);

        scroll=new ScrollView(this);
        scroll.setFillViewport(true);
        history=new LinearLayout(this);
        history.setOrientation(LinearLayout.VERTICAL);
        history.setPadding(Ui.dp(root,4),Ui.dp(root,8),Ui.dp(root,4),Ui.dp(root,16));
        scroll.addView(history,new ScrollView.LayoutParams(-1,-2));
        root.addView(scroll,new LinearLayout.LayoutParams(-1,0,1f));

        LinearLayout composer=new LinearLayout(this);
        composer.setGravity(Gravity.BOTTOM);
        composer.setPadding(0,Ui.dp(root,8),0,Ui.dp(root,2));

        LinearLayout inputShell=new LinearLayout(this);
        inputShell.setGravity(Gravity.BOTTOM);
        inputShell.setMinimumHeight(Ui.dp(root,52));
        inputShell.setBackgroundResource(R.drawable.composer_background);
        inputShell.setPadding(Ui.dp(root,8),Ui.dp(root,4),Ui.dp(root,6),Ui.dp(root,4));

        input=new EditText(this);
        input.setHint(R.string.message_hint);
        input.setTextColor(getColor(R.color.lemenzo_text_primary));
        input.setHintTextColor(getColor(R.color.lemenzo_text_muted));
        input.setTextSize(SettingsActivity.messageTextSize(this));
        input.setSingleLine(false);
        input.setMaxLines(5);
        input.setMaxHeight(Ui.dp(root,124));
        input.setMinHeight(Ui.dp(root,44));
        input.setGravity(Gravity.CENTER_VERTICAL);
        input.setBackgroundColor(0x00000000);
        input.setPadding(Ui.dp(root,6),0,Ui.dp(root,2),0);
        inputShell.addView(input,new LinearLayout.LayoutParams(0,-2,1f));

        LinearLayout.LayoutParams shellParams=new LinearLayout.LayoutParams(0,-2,1f);
        shellParams.setMargins(0,0,Ui.dp(root,9),0);
        composer.addView(inputShell,shellParams);

        send=Ui.iconButton(this,R.drawable.ic_send,getString(R.string.send_message));
        send.setBackgroundResource(R.drawable.round_blue_button);
        send.setPadding(Ui.dp(root,14),Ui.dp(root,14),Ui.dp(root,14),Ui.dp(root,14));
        send.setOnClickListener(v->sendAgain());
        composer.addView(send,new LinearLayout.LayoutParams(Ui.dp(root,52),Ui.dp(root,52)));

        root.addView(composer);
        setContentView(root);
    }

    private void render(){
        BroadcastRecord r=store.get(id);
        if(r==null){finish();return;}

        headerName.setText(r.displayName());
        String subtitle=getString(R.string.recipient_count,r.total);
        if(r.title!=null&&!r.title.trim().isEmpty()){
            subtitle=r.title+" · "+subtitle;
        }
        headerSubtitle.setText(subtitle);

        history.removeAllViews();

        for(BroadcastRecord.Message message:r.messages){
            addMessageBubble(message);
        }

        scroll.post(()->scroll.fullScroll(ScrollView.FOCUS_DOWN));
    }

    private void addMessageBubble(BroadcastRecord.Message message){
        LinearLayout bubble=new LinearLayout(this);
        bubble.setOrientation(LinearLayout.VERTICAL);
        bubble.setBackgroundResource(R.drawable.bubble_outgoing);
        bubble.setPadding(Ui.dp(history,14),Ui.dp(history,11),Ui.dp(history,14),Ui.dp(history,9));

        TextView body=Ui.text(this,message.body,SettingsActivity.messageTextSize(this),false);
        bubble.addView(body);

        LinearLayout meta=new LinearLayout(this);
        meta.setGravity(Gravity.CENTER_VERTICAL|Gravity.END);
        // Preserve one aggregate accessibility description while rendering
        // Sent / Failed / Sending as separate, readable colored labels.
        meta.setContentDescription(statusSummary(message));

        TextView sentStatus=Ui.text(
                this,getString(R.string.broadcast_sent_count,message.sent),13.8f,true);
        sentStatus.setTextColor(getColor(R.color.lemenzo_broadcast_sent));
        meta.addView(sentStatus);

        TextView failedStatus=Ui.text(
                this,getString(R.string.broadcast_failed_count,message.failed),13.8f,true);
        failedStatus.setTextColor(getColor(R.color.lemenzo_broadcast_time));
        LinearLayout.LayoutParams failedLp=new LinearLayout.LayoutParams(-2,-2);
        failedLp.setMargins(Ui.dp(history,10),0,0,0);
        meta.addView(failedStatus,failedLp);

        int pending=message.pending();
        if(pending>0){
            TextView sendingStatus=Ui.text(
                    this,getString(R.string.broadcast_sending_count,pending),13.2f,true);
            sendingStatus.setTextColor(getColor(R.color.lemenzo_broadcast_sending));
            LinearLayout.LayoutParams sendingLp=new LinearLayout.LayoutParams(-2,-2);
            sendingLp.setMargins(Ui.dp(history,10),0,0,0);
            meta.addView(sendingStatus,sendingLp);
        }

        TextView time=Ui.text(this,
                DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date(message.date)),
                12.8f,true);
        time.setTextColor(getColor(R.color.lemenzo_broadcast_time));
        LinearLayout.LayoutParams timeLp=new LinearLayout.LayoutParams(-2,-2);
        timeLp.setMargins(Ui.dp(history,12),0,0,0);
        meta.addView(time,timeLp);

        LinearLayout.LayoutParams metaLp=new LinearLayout.LayoutParams(-1,-2);
        metaLp.setMargins(0,Ui.dp(history,8),0,0);
        bubble.addView(meta,metaLp);

        bubble.setOnLongClickListener(v -> {
            copyBroadcastMessage(message);
            return true;
        });

        LinearLayout.LayoutParams bubbleLp=new LinearLayout.LayoutParams(-1,-2);
        bubbleLp.setMargins(Ui.dp(history,50),Ui.dp(history,5),0,Ui.dp(history,7));
        history.addView(bubble,bubbleLp);
    }

    private void copyBroadcastMessage(BroadcastRecord.Message message){
        if(message==null||message.body==null||message.body.isEmpty())return;
        ClipboardManager clipboard=getSystemService(ClipboardManager.class);
        if(clipboard==null)return;
        clipboard.setPrimaryClip(
                ClipData.newPlainText(getString(R.string.app_title),message.body));
        Toast.makeText(this,R.string.message_copied,Toast.LENGTH_SHORT).show();
    }

    private void sendAgain(){
        if(sendInFlight)return;
        BroadcastRecord record=store.get(id);
        if(record==null||record.recipients.isEmpty())return;

        String text=input.getText().toString().trim();
        if(text.isEmpty())return;

        final ArrayList<BroadcastRecord.Recipient> recipients=
                new ArrayList<>(record.recipients);

        SubscriptionHelper.choose(this,subscriptionId->{
            String messageId=store.beginMessage(id,text);
            if(messageId==null)return;

            input.setText("");
            sendInFlight=true;
            send.setEnabled(false);
            send.setAlpha(0.55f);
            input.setEnabled(false);

            sendExecutor.execute(()->{
                for(BroadcastRecord.Recipient recipient:recipients){
                    boolean accepted=SmsSender.sendBroadcastRecipient(
                            getApplicationContext(),
                            recipient.number,
                            text,
                            subscriptionId,
                            id,
                            messageId);
                    if(!accepted){
                        store.updateRecipient(id,messageId,recipient.number,"failed");
                    }
                    try{Thread.sleep(25L);}catch(InterruptedException e){
                        Thread.currentThread().interrupt();
                        break;
                    }
                }

                runOnUiThread(()->{
                    sendInFlight=false;
                    if(isFinishing()||isDestroyed())return;
                    input.setEnabled(true);
                    send.setEnabled(true);
                    send.setAlpha(1f);
                    input.requestFocus();
                    render();
                });
            });
        });
    }

    private String statusSummary(BroadcastRecord.Message m){
        int pending=m.pending();
        if(pending>0){
            return getString(R.string.broadcast_status_progress,m.sent,m.failed,pending);
        }
        return getString(R.string.broadcast_status_complete,m.sent,m.failed);
    }
}
