package com.algobase.share.activity;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;

import java.lang.Process;

/*
import android.app.Activity;
*/
import android.content.Intent;
import android.content.DialogInterface;
import android.content.res.Resources;

import android.graphics.Color;
import android.graphics.Typeface;

import android.os.Build;
import android.os.Bundle;
import android.os.FileObserver;

import android.util.Log;
import android.util.TypedValue;

import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;

import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ScrollView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;

import android.net.Uri;

import androidx.core.content.FileProvider;
import com.algobase.share.dialog.*;

import com.algobase.share.compat.Activity;


public class FileViewerActivity extends Activity 
{

     static final int GREY = 0xffdddddd;
     static final int BLUE = 0xff003d8f;
     static final int DARKBLUE = 0xff00285e;
     static final int YELLOW = 0xffeeee77;


     int title_bg_clr = BLUE;
     int title_hi_clr = YELLOW;



     String file_name;
     int menu_image = 0;

     File file;

     String filter = null;
     String find_pattern= "";

     int buf_size = 1 << 16;

     String[] buffer = new String[buf_size];
     int line_count = 0;
     int selection = -1;

     long bytes = 0;

     LinearLayout layout;
     ListView lv;
     BaseAdapter adapter;

     LinearLayout title_layout;
     TextView title_text;
     ImageButton menu_button;

     LinearLayout bottom_layout;
     TextView bottom_left;
     TextView bottom_right;

     TextView tv;
     Button but1;
     Button but2;

     MyPopupMenu popup_menu;

     long last_modified = 0;
     

     void showToast(String txt) {
       Toast.makeText(this,txt,Toast.LENGTH_SHORT).show();
     }

    int DipToPixel(float dp)
    { float dpi = getResources().getDisplayMetrics().densityDpi;
      return (int)(dp * (dpi/160f));
     }


   void sendFile(File file)
   { String addr[] = new String[]{"stefan.naeher@gmail.com"};
     Intent intent = new Intent(Intent.ACTION_SEND);
     intent.putExtra(Intent.EXTRA_EMAIL,addr);
     intent.putExtra(Intent.EXTRA_SUBJECT,file.getName());
     intent.putExtra(Intent.EXTRA_TEXT,file.getName());
     //intent.setType("plain/text");
     intent.setType("message/rfc822");

     Uri uri = FileProvider.getUriForFile(this,getPackageName(),file);
     intent.putExtra(Intent.EXTRA_STREAM, uri);

     startActivity(Intent.createChooser(intent,"Export"));
   }

   void loadFile()
   {
     title_text.setText(file.getName());

     if (!file.exists()) return;

     //showToast("Loading");

     line_count = 0;

     bytes =  0;

     try
     { FileReader fr = new FileReader(file);
       BufferedReader br = new BufferedReader(fr);
       String line;
       while ((line = br.readLine()) != null) {
         if (filter != null && 
             line.toLowerCase().indexOf(filter) == -1) continue;
         if (line_count < buffer.length) buffer[line_count] = line;
         line_count++;
         bytes += line.length() + 1;
       }
       fr.close();
       br.close();
     } catch (IOException e) { showToast("FileViewer: " + e.toString());}

     //showToast("" + bytes + " Bytes");

     if (line_count > buffer.length) {
        showToast("" + line_count + "  Lines");
        line_count = buffer.length;
     }

     bottom_left.setText("" + line_count);

     adapter.notifyDataSetChanged();
   }


  void filter_dialog() 
  {
    final MyDialog dialog = new MyDialog(this);
    dialog.setTitle("Filter");

    final EditText edit = dialog.newEditText();
    //edit.setText("");
    edit.setTextSize(20);
    edit.requestFocus();

    dialog.setView(edit);

    dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface d, int which) {
                         filter = edit.getText().toString().toLowerCase();
                         loadFile();
                }
     });

     dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface d, int which) {
                         filter = null;
                         loadFile();
                }
     });

    dialog.show();

  }

  void find_dialog() 
  {
    final MyDialog dialog = new MyDialog(this);
    dialog.setTitle("Find");

    final EditText edit = dialog.newEditText();
    edit.setText(find_pattern);
    edit.setTextSize(20);
    edit.requestFocus();

    dialog.setView(edit);

    dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface d, int which) {
               find_pattern = edit.getText().toString().toLowerCase();
               findNext();
            }
     });

     dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface d, int which) { 
                find_pattern = "";
                selection = -1;
                adapter.notifyDataSetChanged();
            }
     });

    dialog.show();

  }
 
 
   void scrollToLine(final int pos)
   { 
     //showToast("scrollTo: " + pos);

     adapter.notifyDataSetChanged();

     lv.post(new Runnable(){
         public void run() { 
           int first = lv.getFirstVisiblePosition();
           int p = pos;

           if (p > first)
           { if (p > first+50) lv.setSelection(p-50);
             //p +=15;
             p +=10;
            }

           if (p < first) 
           { if (p < first-25) lv.setSelection(p+25);
             //p -=10;
             p -=5;
            }

           lv.smoothScrollToPosition(p); 
         }
     });

   }




   void findNext()
   { if (find_pattern.equals("")) return;

     int p = selection;
     selection = -1;

     for(int i=0; i<line_count; i++)
     { p = (p + 1) % line_count; 
       if (buffer[p].toLowerCase().indexOf(find_pattern) != -1)
       { selection = p;
         break;
       }
     }
  
     if (selection == -1) {
       showToast("Pattern not found");
       return;
     }

   //showToast("sel = " + selection);

     scrollToLine(selection);
     adapter.notifyDataSetChanged();
  }


  void init_menu()
  {
    popup_menu = new MyPopupMenu(this) {
        @Override
        public void callMenuAction(View view, int p, final int i) {
            switch(i) {

             case 1: scrollToLine(0);
                     break;

             case 2: loadFile();
                     scrollToLine(line_count-1);
                     break;

             case 3: sendFile(file);
                     break;

             case 4: filter_dialog();
                     break;

             case 5: find_dialog();
                     break;

             case 6: { Intent extra = new Intent();
                       extra.putExtra("file_viewer","ok");
                       setResult(RESULT_OK, extra);
                       FileViewerActivity.this.finish();
                       break;
                     }

            }
        }

        @Override
        public void dismissHandler() {}
   };

   popup_menu.setAnchorView(menu_button);
   popup_menu.setAutoDismiss(true);
   popup_menu.setTextSize(19);

   popup_menu.setWidth(175);

/*
   popup_menu.add("Top",   0,1);
   popup_menu.add("Bottom",0,2);
*/
   popup_menu.add("Export",0,3);
   popup_menu.add("Filter",0,4);
   popup_menu.add("Find",  0,5);
   popup_menu.add("Exit",  0,6);
 }

     
   @Override
   public void onCreate(Bundle savedInstanceState) 
   {
/*
     int style = MyDialog.STYLE_HOLO_LIGHT;
     MyDialog.setStyle(style);
*/

     requestWindowFeature(Window.FEATURE_NO_TITLE);

     // set system bar color
     Window win = getWindow();
     win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
     win.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
     win.setStatusBarColor(DARKBLUE);

     super.onCreate(savedInstanceState);


     Bundle bundle = this.getIntent().getExtras();
     file_name = bundle.getString("file_name");
     menu_image = bundle.getInt("menu_image",0);

     file = new File(file_name);

     int dp = DipToPixel(1);
     
     // title line
     title_layout = new LinearLayout(this);
     title_layout.setOrientation(LinearLayout.HORIZONTAL);

     title_text = new TextView(this);
     title_text.setTextSize(18);
     title_text.setSingleLine(true);
     title_text.setTextColor(0xffffffff);
     title_text.setTypeface(null,Typeface.BOLD);
     title_text.setBackgroundColor(title_bg_clr);
     title_text.setPadding(10*dp,2*dp,2*dp,3*dp);
     title_text.setGravity(Gravity.CENTER_VERTICAL);

     title_text.setClickable(true);
     title_text.setOnClickListener(new OnClickListener() {
       public void onClick(View v) { scrollToLine(0); }
     });


     title_layout.addView(title_text);
     ((LayoutParams)title_text.getLayoutParams()).width = LayoutParams.FILL_PARENT;
     ((LayoutParams)title_text.getLayoutParams()).height = LayoutParams.FILL_PARENT;
     ((LayoutParams)title_text.getLayoutParams()).weight = 1.0f;


     if (menu_image > 0)
     { menu_button = new ImageButton(this);
       menu_button.setPadding(10*dp,7*dp,10*dp,10*dp);
       menu_button.setBackgroundColor(title_bg_clr);
       menu_button.setImageResource(menu_image);
 
       menu_button.setOnTouchListener(new OnTouchListener() {
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN)
                      v.setBackgroundColor(title_hi_clr);
                    else
                    if (event.getAction() == MotionEvent.ACTION_UP)
                      v.setBackgroundColor(title_bg_clr);
                    return false;
                }
        });
 
       menu_button.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
            //popup_menu.show(+1,-10);
            popup_menu.show(+2000,-10);
          }
       });
 
       title_layout.addView(menu_button);
       LayoutParams params = (LayoutParams)menu_button.getLayoutParams();
       params.leftMargin=dp;
       params.height=LayoutParams.MATCH_PARENT;
     }


     // bottom line
     bottom_layout = new LinearLayout(this);
     bottom_layout.setOrientation(LinearLayout.HORIZONTAL);

     bottom_left = new TextView(this);
     bottom_left.setTextSize(18);
     bottom_left.setSingleLine(true);
     bottom_left.setTextColor(0xff222222);
     bottom_left.setBackgroundColor(GREY);
     bottom_left.setPadding(10*dp,2*dp,2*dp,3*dp);
     bottom_left.setGravity(Gravity.CENTER_VERTICAL);

     bottom_right = new TextView(this);
     bottom_right.setTextSize(18);
     bottom_right.setSingleLine(true);
     bottom_right.setTextColor(0xff222222);
     bottom_right.setBackgroundColor(GREY);
     bottom_right.setPadding(2*dp,2*dp,12*dp,3*dp);
     bottom_right.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);

     bottom_layout.addView(bottom_left);
     ((LayoutParams)bottom_left.getLayoutParams()).width = LayoutParams.FILL_PARENT;
     ((LayoutParams)bottom_left.getLayoutParams()).weight = 1.0f;

     bottom_layout.addView(bottom_right);
     ((LayoutParams)bottom_right.getLayoutParams()).width = 200*dp;
/*
     ((LayoutParams)bottom_right.getLayoutParams()).width = LayoutParams.WRAP_CONTENT;
*/


     lv = new ListView(this);

     adapter = new BaseAdapter() {
          @Override
          public int getCount() { return line_count; }

          @Override
          public Object getItem(int pos) { return buffer[pos]; }

          @Override
          public long getItemId(int pos) { return pos; }

          @Override
          public View getView(int pos, View v, ViewGroup parent)
          { TextView tv = (TextView)v;
            if (tv == null) tv =  new TextView(FileViewerActivity.this);
            tv.setBackgroundColor(Color.BLACK);
            tv.setPadding(5*dp,1*dp,1*dp,0*dp);
/*
            tv.setTextSize(14);
*/
            tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP,19);
            tv.setTypeface(Typeface.MONOSPACE);

            if (pos == selection)
              tv.setTextColor(Color.YELLOW);
            else
              tv.setTextColor(Color.WHITE);
            tv.setText(buffer[pos]);
            tv.setClickable(true);

            tv.setOnClickListener(new OnClickListener() {
              public void onClick(View v) { 
                  if (find_pattern.equals(""))
                  { loadFile();
                    scrollToLine(line_count-1);
                   }
                  else
                    findNext();
              }
            });

            return tv;
           }
        };

     lv.setAdapter(adapter);

     lv.setOnScrollListener(new OnScrollListener() {
         @Override
         public void onScrollStateChanged(AbsListView view, int state) {}

         @Override
         public void onScroll(AbsListView view, int first_visible, 
                                                int visible_items, 
                                                int total_items) {
            int bottom_item = first_visible + visible_items;
            bottom_left.setText("" + bottom_item + " / " + total_items);
/*
            int percent = 0;
            if (total_items > 0) { 
              percent = (int)(0.5f + (100.0f*bottom_item)/total_items);
            }
            bottom_right.setText("" + percent + " %");
*/
            bottom_right.setText("" + bytes);
         }
     });

 
     // build main layout

     layout = new LinearLayout(this);
     layout.setOrientation(LinearLayout.VERTICAL);

     if (Build.VERSION.SDK_INT >= 35) {
       adjustLayout(layout,0xff222222);
     }

     layout.addView(title_layout);

   //((LayoutParams)title_layout.getLayoutParams()).height = 42*dp;

     layout.addView(lv);
     ((LayoutParams)lv.getLayoutParams()).width = LayoutParams.FILL_PARENT;
     ((LayoutParams)lv.getLayoutParams()).height = LayoutParams.FILL_PARENT;
     ((LayoutParams)lv.getLayoutParams()).weight = 1.0f;

     layout.addView(bottom_layout);

     setContentView(layout);

     init_menu();
     loadFile();
    
/*
     FileObserver observer = new FileObserver(file.getPath()) {
          @Override
          public void onEvent(int event, String path) {
                 showToast("event= " + event + "  path = " + path);
          }
     };
   
     observer.startWatching();
*/

    }  


    @Override
    protected void onDestroy() {
      super.onDestroy();
    }

    @Override
    protected void onRestart() {
	super.onRestart();
    }

    @Override
    protected void onStart() {
	super.onStart();
    }
    

    @Override
    protected void onResume() {
      super.onResume();
     }

    @Override
    protected void onPause() {
      super.onPause();
    }

    @Override
    protected void onStop() {
	super.onStop();
    }

    
   @Override
   public void onBackPressed() 
   { Intent extra = new Intent();
     extra.putExtra("file_viewer","ok");
     setResult(RESULT_OK, extra);
     super.onBackPressed();
    }

 

    private class MyFileObserver extends FileObserver {
        
        public String file_path;
        
        public MyFileObserver(String path) {
            super(path, FileObserver.ALL_EVENTS);
            file_path = path;
            showToast("observer: file = " + path);
        }
        
        @Override
        public void onEvent(int event, String path) {
            
            showToast("event:path = " + path);
            
            if (path == null) {
                return;
            }
            
            //a new file or subdirectory was created under the monitored directory
            if ((FileObserver.CREATE & event)!=0) {
                
            }
            //a file or directory was opened
            if ((FileObserver.OPEN & event)!=0) {
                
            }
            //data was read from a file
            if ((FileObserver.ACCESS & event)!=0) {
               
            }
            //data was written to a file
            if ((FileObserver.MODIFY & event)!=0) {
                //showToast("written: " + path);
                loadFile();
            }

            //someone has a file or directory open read-only, and closed it
            if ((FileObserver.CLOSE_NOWRITE & event)!=0) {
                
            }
            //someone has a file or directory open for writing, and closed it 
            if ((FileObserver.CLOSE_WRITE & event)!=0) {
                
            }
            //[todo: consider combine this one with one below]
            //a file was deleted from the monitored directory
            if ((FileObserver.DELETE & event)!=0) {

            }
            //the monitored file or directory was deleted, monitoring effectively stops
            if ((FileObserver.DELETE_SELF & event)!=0) {
                
            }
            //a file or subdirectory was moved from the monitored directory
            if ((FileObserver.MOVED_FROM & event)!=0) {
                
            }
            //a file or subdirectory was moved to the monitored directory
            if ((FileObserver.MOVED_TO & event)!=0) {
                
            }
            //the monitored file or directory was moved; monitoring continues
            if ((FileObserver.MOVE_SELF & event)!=0) {
                
            }
            //Metadata (permissions, owner, timestamp) was changed explicitly
            if ((FileObserver.ATTRIB & event)!=0) {
                
            }
        }
    }
}
