/*
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.

  Keepass2Android is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Keepass2Android is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Keepass2Android.  If not, see <http://www.gnu.org/licenses/>.
  */
using System;
using System.Linq;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using KeePassLib;
using Android.Text;
using Android.Text.Style;
using Android.Preferences;
using KeePass.Util.Spr;
using KeeTrayTOTP.Libraries;
using PluginTOTP;
using Android.Content;
using System.ComponentModel;
using keepass2android;


namespace keepass2android.view
{
	public sealed class PwEntryView : GroupListItemView
	{
		private readonly GroupBaseActivity _groupActivity;
		private PwEntry _entry;
		private readonly TextView _textView;
		private readonly TextView _textviewDetails;
		private readonly TextView _textgroupFullPath;
        private readonly ProgressBar _totpCountdown;
        private readonly TextView _totpText;
        private readonly LinearLayout _totpLayout;

        private int _pos;

		private int? _defaultTextColor;

		readonly bool _showDetail;
		readonly bool _showGroupFullPath;
		readonly bool _isSearchResult;


		private const int MenuOpen = Menu.First;
		private const int MenuDelete = MenuOpen + 1;
		private const int MenuMove = MenuDelete + 1;
		private const int MenuNavigate = MenuMove + 1;
		
		public static PwEntryView GetInstance(GroupBaseActivity act, PwEntry pw, int pos)
		{
			return new PwEntryView(act, pw, pos);

		}

		public PwEntryView(IntPtr javaReference, JniHandleOwnership transfer)
			: base(javaReference, transfer)
		{
			
		}

		private PwEntryView(GroupBaseActivity groupActivity, PwEntry pw, int pos):base(groupActivity)
		{
			_groupActivity = groupActivity;

            View ev = Inflate(groupActivity, Resource.Layout.entry_list_entry, null);
			_textView = (TextView)ev.FindViewById(Resource.Id.entry_text);
			_textView.TextSize = PrefsUtil.GetListTextSize(groupActivity);

		    Database db = App.Kp2a.FindDatabaseForElement(pw);
			
			ev.FindViewById(Resource.Id.entry_icon_bkg).Visibility = db.DrawableFactory.IsWhiteIconSet ?  ViewStates.Visible : ViewStates.Gone;

			_textviewDetails = (TextView)ev.FindViewById(Resource.Id.entry_text_detail);
			_textviewDetails.TextSize = PrefsUtil.GetListDetailTextSize(groupActivity);

			_textgroupFullPath = (TextView)ev.FindViewById(Resource.Id.group_detail);
			_textgroupFullPath.TextSize = PrefsUtil.GetListDetailTextSize(groupActivity);

            _totpCountdown = ev.FindViewById<ProgressBar>(Resource.Id.TotpCountdownProgressBar);
            _totpText = ev.FindViewById<TextView>(Resource.Id.totp_text);
            _totpLayout = ev.FindViewById<LinearLayout>(Resource.Id.totp_layout);

            _totpLayout.LongClick += (sender, args) =>
            {
                string totp = UpdateTotp();
                if (!String.IsNullOrEmpty(totp))
                    CopyToClipboardService.CopyValueToClipboardWithTimeout(_groupActivity, totp, true);
            };

            _showDetail = PreferenceManager.GetDefaultSharedPreferences(groupActivity).GetBoolean(
				groupActivity.GetString(Resource.String.ShowUsernameInList_key), 
				Resources.GetBoolean(Resource.Boolean.ShowUsernameInList_default));

			_showGroupFullPath = PreferenceManager.GetDefaultSharedPreferences(groupActivity).GetBoolean(
				groupActivity.GetString(Resource.String.ShowGroupnameInSearchResult_key), 
				Resources.GetBoolean(Resource.Boolean.ShowGroupnameInSearchResult_default));

			_isSearchResult = _groupActivity is keepass2android.search.SearchResults;


			PopulateView(ev, pw, pos);
			
			LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
			
			AddView(ev, lp);
			
		}
		
		private void PopulateView(View ev, PwEntry pw, int pos)
		{

            if (_groupBaseActivity.IsFinishing)
                return;

            _entry = pw;
			_pos = pos;
		    ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible;
		    ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible;

		    _db = App.Kp2a.FindDatabaseForElement(_entry);

            ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon);
			bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now;
			if (isExpired)
			{
				_db.DrawableFactory.AssignDrawableTo(iv, Context, _db.KpDatabase, PwIcon.Expired, PwUuid.Zero, false);
			} else
			{
				_db.DrawableFactory.AssignDrawableTo(iv, Context, _db.KpDatabase, pw.IconId, pw.CustomIconUuid, false);
			}

			String title = pw.Strings.ReadSafe(PwDefs.TitleField);
            title = SprEngine.Compile(title, new SprContext(_entry, _db.KpDatabase, SprCompileFlags.All));
            var str = new SpannableString(title);

			if (isExpired)
			{
				str.SetSpan(new StrikethroughSpan(), 0, title.Length, SpanTypes.ExclusiveExclusive);
			}
			_textView.TextFormatted = str;

			if (_defaultTextColor == null)
				_defaultTextColor = _textView.TextColors.DefaultColor;

			if (_groupActivity.IsBeingMoved(_entry.Uuid))
			{
				int elementBeingMoved = Context.Resources.GetColor(Resource.Color.md_theme_inversePrimary);
				_textView.SetTextColor(new Color(elementBeingMoved));
			}
			else
				_textView.SetTextColor(new Color((int)_defaultTextColor));

			String detail = pw.Strings.ReadSafe(PwDefs.UserNameField);
			detail = SprEngine.Compile(detail, new SprContext(_entry, _db.KpDatabase, SprCompileFlags.All));

			if ((_showDetail == false) || (String.IsNullOrEmpty(detail)))
			{
				_textviewDetails.Visibility = ViewStates.Gone;
			}
			else
			{
				var strDetail = new SpannableString(detail);
				
				if (isExpired)
				{
					strDetail.SetSpan(new StrikethroughSpan(), 0, detail.Length, SpanTypes.ExclusiveExclusive);
				}
				_textviewDetails.TextFormatted = strDetail;

				_textviewDetails.Visibility = ViewStates.Visible;
			}
				
			if ( (!_showGroupFullPath) || (!_isSearchResult) ) {
				_textgroupFullPath.Visibility = ViewStates.Gone;
			}

			else {
				String groupDetail = pw.ParentGroup.GetFullPath();
			    if (App.Kp2a.OpenDatabases.Count() > 1)
			    {
			        groupDetail += "(" + App.Kp2a.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
			    }

				var strGroupDetail = new SpannableString (groupDetail);

				if (isExpired) {
					strGroupDetail.SetSpan (new StrikethroughSpan (), 0, groupDetail.Length, SpanTypes.ExclusiveExclusive);
				}
				_textgroupFullPath.TextFormatted = strGroupDetail;

				_textgroupFullPath.Visibility = ViewStates.Visible;
			}

			//try to get totp data
            UpdateTotp();
            

           
                

            

        }
		
		public void ConvertView(PwEntry pw, int pos)
		{
			PopulateView(this, pw, pos);
		}

		
		private void LaunchEntry()
		{
			_groupActivity.LaunchActivityForEntry(_entry, _pos);
			//_groupActivity.OverridePendingTransition(Resource.Animation.anim_enter, Resource.Animation.anim_leave);
		}
		/*
		public override void OnCreateMenu(IContextMenu menu, IContextMenuContextMenuInfo menuInfo)
		{
			menu.Add(0, MenuOpen, 0, Resource.String.menu_open);
			if (App.Kp2a.GetDb().CanWrite)
			{
				menu.Add(0, MenuDelete, 0, Resource.String.menu_delete);
				menu.Add(0, MenuMove, 0, Resource.String.menu_move);

				if (_isSearchResult) {
					menu.Add (0, MenuNavigate, 0, Resource.String.menu_navigate);
				}

			}
		}
		
		public override bool OnContextItemSelected(IMenuItem item)
		{
			switch (item.ItemId)
			{
				
				case MenuOpen:
					LaunchEntry();
					return true;
				case MenuDelete:
					Handler handler = new Handler();
					DeleteEntry task = new DeleteEntry(Context, App.Kp2a, _entry, new GroupBaseActivity.RefreshTask(handler, _groupActivity));
					task.Start();
					return true;
				case MenuMove:
					NavigateToFolderAndLaunchMoveElementTask navMove = 
						new NavigateToFolderAndLaunchMoveElementTask(_entry.ParentGroup, _entry.Uuid, _isSearchResult);
					_groupActivity.StartTask (navMove);
					return true;
				case MenuNavigate: 
					NavigateToFolder navNavigate = new NavigateToFolder(_entry.ParentGroup, true);
					_groupActivity.StartTask (navNavigate);
					return true;

				default:
					return false;
			}
		}

		*/
	    public override void OnClick()
	    {
	        LaunchEntry();
	    }

        
        
        private TotpData _totpData;
		
        private Database _db;

        public string UpdateTotp()
        {
            ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(_groupActivity);
            bool showTotpDefault = _groupActivity.MayPreviewTotp;
                

            if (showTotpDefault)
                _totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(_entry, _db));
			else
			    _totpData = null;

            if (_totpData?.IsTotpEntry != true)
            {
                _totpLayout.Visibility = ViewStates.Gone;
                return null;
            }

            _totpLayout.Visibility = ViewStates.Visible;

            TOTPProvider prov = new TOTPProvider(_totpData);
            string totp = prov.GenerateByByte(_totpData.TotpSecret);

            _totpText.Text = totp;
            var progressBar = _totpCountdown;
            progressBar.Progress = prov.Timer;
            progressBar.Max = prov.Duration;

            return totp;
        }
    }
}

