package com.lemenzo.contacts;

import android.app.*;
import android.content.*;
import android.graphics.*;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import java.io.*;
import java.util.*;

public class ContactEditorActivity extends Activity {
    private static final int PICK_PHOTO = 711;
    private static final int REQ_CONTACTS = 712;

    private ContactsRepository repo;
    private ContactData d;
    private EditText first,middle,last,display,company,title,address,birthday,notes;
    private LinearLayout phones,emails;
    private ImageView photo;
    private Button photoButton,removePhotoButton;
    private boolean editorBuilt;

    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
        repo = new ContactsRepository(this);

        if (!ContactsPermission.hasReadWrite(this)) {
            ContactsPermission.requestReadWrite(this, REQ_CONTACTS);
            return;
        }

        loadAndBuildEditor();
    }

    private void loadAndBuildEditor() {
        if (editorBuilt || isFinishing() || isDestroyed()) return;

        final long id = getIntent().getLongExtra("contact_id", -1);
        try {
            d = id > 0 ? repo.getForEdit(id) : new ContactData();
        } catch (SecurityException e) {
            handlePermissionFailure();
            return;
        } catch (RuntimeException e) {
            Toast.makeText(this, R.string.contact_load_failed, Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        String initialName = getIntent().getStringExtra("initial_name");
        String initialPhone = getIntent().getStringExtra("initial_phone");
        String initialEmail = getIntent().getStringExtra("initial_email");
        int initialPhoneType = getIntent().getIntExtra("initial_phone_type", 2);

        if (initialName != null && !initialName.trim().isEmpty()
                && (id <= 0 || d.displayName == null || d.displayName.trim().isEmpty())) {
            d.displayName = initialName.trim();
        }
        if (initialPhone != null && !initialPhone.trim().isEmpty()
                && !containsNormalized(d.phones, initialPhone.trim())) {
            d.phones.add(initialPhone.trim());
            d.phoneTypes.add(initialPhoneType > 0 ? initialPhoneType : 2);
        }
        if (initialEmail != null && !initialEmail.trim().isEmpty()
                && !containsIgnoreCase(d.emails, initialEmail.trim())) {
            d.emails.add(initialEmail.trim());
            d.emailTypes.add(1);
        }

        if (id > 0 && !d.localEditable) {
            Toast.makeText(this, R.string.external_contact_read_only, Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        editorBuilt = true;
        build();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode != REQ_CONTACTS) return;

        if (ContactsPermission.hasReadWrite(this)) {
            loadAndBuildEditor();
        } else {
            Toast.makeText(this, R.string.contacts_permission_required, Toast.LENGTH_LONG).show();
            finish();
        }
    }

    private void handlePermissionFailure() {
        if (!ContactsPermission.hasReadWrite(this)) {
            ContactsPermission.requestReadWrite(this, REQ_CONTACTS);
        } else {
            Toast.makeText(this, R.string.contacts_permission_required, Toast.LENGTH_LONG).show();
            finish();
        }
    }

    private void build() {
        LinearLayout root=new LinearLayout(this);root.setOrientation(LinearLayout.VERTICAL);root.setBackgroundColor(Ui.BG);Ui.applySafeInsets(this,root);
        LinearLayout top=new LinearLayout(this);top.setGravity(Gravity.CENTER_VERTICAL);top.setPadding(Ui.dp(this,16),0,Ui.dp(this,16),0);
        TextView cancel=Ui.text(this,getString(R.string.cancel),14,Ui.BLUE);cancel.setGravity(Gravity.START|Gravity.CENTER_VERTICAL);cancel.setOnClickListener(v->finish());top.addView(cancel,new LinearLayout.LayoutParams(Ui.dp(this,72),Ui.dp(this,54)));
        TextView heading=Ui.title(this,d.contactId>0?getString(R.string.edit):getString(R.string.add_contact),17);heading.setGravity(Gravity.CENTER);top.addView(heading,new LinearLayout.LayoutParams(0,Ui.dp(this,54),1));
        TextView topSave=Ui.title(this,getString(R.string.save),14);topSave.setTextColor(Ui.BLUE);topSave.setGravity(Gravity.END|Gravity.CENTER_VERTICAL);topSave.setOnClickListener(v->save());top.addView(topSave,new LinearLayout.LayoutParams(Ui.dp(this,72),Ui.dp(this,54)));
        root.addView(top);
        ScrollView sv=new ScrollView(this);LinearLayout box=new LinearLayout(this);box.setOrientation(LinearLayout.VERTICAL);box.setPadding(Ui.dp(this,16),0,Ui.dp(this,16),Ui.dp(this,24));
        photo=new ImageView(this);photo.setScaleType(ImageView.ScaleType.CENTER_CROP);photo.setBackground(Ui.outline(this,Ui.SURFACE2,Ui.BLUE,46));photo.setClipToOutline(true);
        if(d.photoBytes!=null)photo.setImageBitmap(BitmapFactory.decodeByteArray(d.photoBytes,0,d.photoBytes.length));else photo.setImageResource(R.drawable.lemenzo_contacts_logo);
        LinearLayout.LayoutParams ph=new LinearLayout.LayoutParams(Ui.dp(this,92),Ui.dp(this,92));ph.gravity=Gravity.CENTER_HORIZONTAL;box.addView(photo,ph);box.addView(Ui.space(this,8));
        photoButton=Ui.button(this,getString(d.photoBytes==null?R.string.add_photo:R.string.change_photo),false);photoButton.setOnClickListener(v->pickPhoto());box.addView(photoButton);
        removePhotoButton=Ui.button(this,getString(R.string.remove_photo),false);removePhotoButton.setTextColor(Ui.DANGER);removePhotoButton.setVisibility(d.photoBytes==null?View.GONE:View.VISIBLE);removePhotoButton.setOnClickListener(v->{d.photoBytes=null;photo.setImageResource(R.drawable.lemenzo_contacts_logo);photoButton.setText(R.string.add_photo);removePhotoButton.setVisibility(View.GONE);});box.addView(Ui.space(this,6));box.addView(removePhotoButton);box.addView(Ui.space(this,16));
        first=field(box,R.string.first_name,d.firstName);middle=field(box,R.string.middle_name,d.middleName);last=field(box,R.string.last_name,d.lastName);display=field(box,R.string.display_name,d.displayName);
        phones=new LinearLayout(this);phones.setOrientation(LinearLayout.VERTICAL);box.addView(Ui.title(this,getString(R.string.phone),14));for(int i=0;i<d.phones.size();i++)addDynamic(phones,R.string.phone,d.phones.get(i),i<d.phoneTypes.size()?d.phoneTypes.get(i):2,true);if(d.phones.isEmpty())addDynamic(phones,R.string.phone,"",2,true);box.addView(phones);Button addP=Ui.button(this,getString(R.string.add_phone),false);addP.setOnClickListener(v->addDynamic(phones,R.string.phone,"",2,true));box.addView(addP);box.addView(Ui.space(this,12));
        emails=new LinearLayout(this);emails.setOrientation(LinearLayout.VERTICAL);box.addView(Ui.title(this,getString(R.string.email),14));for(int i=0;i<d.emails.size();i++)addDynamic(emails,R.string.email,d.emails.get(i),i<d.emailTypes.size()?d.emailTypes.get(i):1,false);if(d.emails.isEmpty())addDynamic(emails,R.string.email,"",1,false);box.addView(emails);Button addE=Ui.button(this,getString(R.string.add_email),false);addE.setOnClickListener(v->addDynamic(emails,R.string.email,"",1,false));box.addView(addE);box.addView(Ui.space(this,12));
        company=field(box,R.string.company,d.company);title=field(box,R.string.job_title,d.jobTitle);address=field(box,R.string.address,d.address);birthday=field(box,R.string.birthday,d.birthday);birthday.setFocusable(false);birthday.setOnClickListener(v->showBirthdayPicker());
        notes=field(box,R.string.notes,d.notes);notes.setSingleLine(false);notes.setMinLines(3);notes.setGravity(Gravity.TOP);notes.setPadding(Ui.dp(this,16),Ui.dp(this,14),Ui.dp(this,16),Ui.dp(this,14));
        sv.addView(box);root.addView(sv,new LinearLayout.LayoutParams(-1,0,1));setContentView(root);
    }

    private void showBirthdayPicker(){
        java.util.Calendar c=java.util.Calendar.getInstance();
        DatePickerDialog dialog=new DatePickerDialog(this,(view,year,month,day)->birthday.setText(String.format(java.util.Locale.ROOT,"%04d-%02d-%02d",year,month+1,day)),c.get(java.util.Calendar.YEAR),c.get(java.util.Calendar.MONTH),c.get(java.util.Calendar.DAY_OF_MONTH));
        dialog.setOnShowListener(v->{dialog.getButton(DatePickerDialog.BUTTON_POSITIVE).setTextColor(Ui.BLUE);dialog.getButton(DatePickerDialog.BUTTON_NEGATIVE).setTextColor(Ui.SECONDARY);});
        dialog.show();
    }

    private void pickPhoto(){Intent i=new Intent(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE).setType("image/*");startActivityForResult(i,PICK_PHOTO);}
    protected void onActivityResult(int r,int result,Intent data){super.onActivityResult(r,result,data);if(r!=PICK_PHOTO||result!=RESULT_OK||data==null||data.getData()==null)return;try(InputStream in=getContentResolver().openInputStream(data.getData())){Bitmap original=BitmapFactory.decodeStream(in);if(original==null)return;int max=512,w=original.getWidth(),h=original.getHeight();float scale=Math.min(1f,(float)max/Math.max(w,h));Bitmap b=scale<1f?Bitmap.createScaledBitmap(original,Math.max(1,Math.round(w*scale)),Math.max(1,Math.round(h*scale)),true):original;ByteArrayOutputStream out=new ByteArrayOutputStream();b.compress(Bitmap.CompressFormat.JPEG,90,out);d.photoBytes=out.toByteArray();photo.setImageBitmap(b);photoButton.setText(R.string.change_photo);removePhotoButton.setVisibility(View.VISIBLE);}catch(Exception e){Toast.makeText(this,R.string.import_failed,Toast.LENGTH_SHORT).show();}}
    private EditText field(LinearLayout b,int hint,String value){EditText e=Ui.input(this,getString(hint));e.setText(value);b.addView(e,new LinearLayout.LayoutParams(-1,Ui.dp(this,54)));b.addView(Ui.space(this,10));return e;}
    private void addDynamic(LinearLayout box,int hint,String value,int type,boolean phone){LinearLayout row=new LinearLayout(this);row.setGravity(Gravity.CENTER_VERTICAL);EditText e=Ui.input(this,getString(hint));e.setText(value);row.addView(e,new LinearLayout.LayoutParams(0,Ui.dp(this,54),1));Spinner sp=new Spinner(this);String[] labels={getString(R.string.type_home),getString(R.string.type_mobile),getString(R.string.type_work),getString(R.string.type_other)};ArrayAdapter<String>a=new ArrayAdapter<>(this,android.R.layout.simple_spinner_dropdown_item,labels);sp.setAdapter(a);int pos=phone?(type==1?0:type==3?2:type==7?3:1):(type==2?2:type==3?3:0);sp.setSelection(pos);sp.setTag(phone);LinearLayout.LayoutParams slp=new LinearLayout.LayoutParams(Ui.dp(this,110),Ui.dp(this,54));slp.leftMargin=Ui.dp(this,8);row.addView(sp,slp);LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(-1,Ui.dp(this,62));lp.bottomMargin=Ui.dp(this,4);box.addView(row,lp);}
    private ArrayList<String> values(LinearLayout box,java.util.List<Integer> types){ArrayList<String>x=new ArrayList<>();types.clear();for(int i=0;i<box.getChildCount();i++){View v=box.getChildAt(i);if(v instanceof LinearLayout){LinearLayout r=(LinearLayout)v;if(r.getChildCount()<2)continue;EditText e=(EditText)r.getChildAt(0);Spinner sp=(Spinner)r.getChildAt(1);String val=e.getText().toString().trim();if(val.isEmpty())continue;x.add(val);boolean phone=Boolean.TRUE.equals(sp.getTag());int pos=sp.getSelectedItemPosition();types.add(phone?(pos==0?1:pos==1?2:pos==2?3:7):(pos==0?1:pos==2?2:3));}}return x;}

    private boolean containsNormalized(java.util.List<String> values, String candidate) {
        String normalized = candidate == null ? "" : candidate.replaceAll("[^0-9+]", "");
        for (String value : values) {
            String existing = value == null ? "" : value.replaceAll("[^0-9+]", "");
            if (!normalized.isEmpty() && normalized.equals(existing)) return true;
        }
        return false;
    }

    private boolean containsIgnoreCase(java.util.List<String> values, String candidate) {
        for (String value : values) if (value != null && value.equalsIgnoreCase(candidate)) return true;
        return false;
    }

    private void save(){
        if (!ContactsPermission.hasReadWrite(this)) {
            ContactsPermission.requestReadWrite(this, REQ_CONTACTS);
            return;
        }

        d.firstName=first.getText().toString().trim();d.middleName=middle.getText().toString().trim();d.lastName=last.getText().toString().trim();d.displayName=display.getText().toString().trim();
        if(d.displayName.isEmpty())d.displayName=(d.firstName+" "+d.lastName).trim();d.phones.clear();d.phones.addAll(values(phones,d.phoneTypes));d.emails.clear();d.emails.addAll(values(emails,d.emailTypes));
        d.company=company.getText().toString().trim();d.jobTitle=title.getText().toString().trim();d.address=address.getText().toString().trim();d.birthday=birthday.getText().toString().trim();d.notes=notes.getText().toString().trim();

        try {
            if(d.contactId>0) repo.replaceLocal(d); else d.contactId=repo.create(d);
            if (d.contactId <= 0) throw new IllegalStateException("Contact provider returned no contact id");
            Toast.makeText(this,R.string.contact_saved,Toast.LENGTH_SHORT).show();
            setResult(RESULT_OK);
            finish();
        } catch (SecurityException e) {
            handlePermissionFailure();
        } catch (RuntimeException e) {
            Toast.makeText(this,R.string.contact_save_failed,Toast.LENGTH_LONG).show();
        }
    }
}
