//------------------------------------------------------------------------------
 public KeyChainSerializer()
 {
     m_keyChainUtils = new KeyChainUtils(() => Android.App.Application.Context,
                                         SettingsConfiguration.KeyStoreFileProtectionPassword,
                                         SettingsConfiguration.KeyStoreFileName,
                                         SettingsBaseConfiguration.EncryptionServiceID);
 }
        //------------------------------------------------------------------------------
        public void Delete(string settingName, SettingBaseAttribute attr)
        {
            SecStatusCode eCode = KeyChainUtils.DeletePasswordForUsername(
                settingName,
                m_serviceName,
                m_synchronizable);

            if (eCode == SecStatusCode.Success)
            {
                InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                         "KeyChainSerializer.Delete - success",
                                                         settingName);
            }
            else
            {
                bool contains = KeyChainUtils.Contains(settingName, m_serviceName, m_synchronizable);
                if (contains)
                {
                    InternalConfiguration.PlatformHelper.Log(LogLevel.Error,
                                                             "KeyChainSerializer.Delete error",
                                                             String.Format("Setting name is {0}. Error code is {1}",
                                                                           settingName,
                                                                           eCode));
                }
                else
                {
                    InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                             "KeyChainSerializer.Delete - no such setting",
                                                             settingName);
                }
            }
        }
        //------------------------------------------------------------------------------
        public void Save(string settingName, SettingBaseAttribute attr, object value)
        {
            var simpleValue = SettingsSerializerHelper.SimplifyObject(value);
            var stringValue = SettingsSerializerHelper.ConvertUsingTypeConverter <String>(simpleValue);

            SecStatusCode eCode = KeyChainUtils.SetPasswordForUsername(
                settingName,
                stringValue,
                m_serviceName,
                m_secAccessible,
                m_synchronizable);

            if (eCode == SecStatusCode.Success)
            {
                InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                         "KeyChainSerializer.Save - success",
                                                         settingName);
            }
            else
            {
                InternalConfiguration.PlatformHelper.Log(LogLevel.Error,
                                                         "KeyChainSerializer.Save - error",
                                                         String.Format("Setting name is {0}. Error code is {1}",
                                                                       settingName,
                                                                       eCode));
            }

            // keychain error handling from Xamarin.Auth
            // https://github.com/xamarin/Xamarin.Auth/blob/master/source/Core/Xamarin.Auth.XamarinIOS/AccountStore/KeyChainAccountStore.Aync.cs
            if (eCode != SecStatusCode.Success)
            {
                StringBuilder sb = new StringBuilder("error = ");
                sb.AppendLine("Could not save value to KeyChain: " + eCode);
                sb.AppendLine("Add Empty Entitlements.plist ");
                sb.AppendLine("File /+ New file /+ iOS /+ Entitlements.plist");

                /*
                 *  Error: Could not save account to KeyChain -- iOS 10 #128
                 *  https://github.com/xamarin/Xamarin.Auth/issues/128
                 *  https://bugzilla.xamarin.com/show_bug.cgi?id=43514
                 */
                if ((int)eCode == -34018)
                {
                    // http://stackoverflow.com/questions/38456471/secitemadd-always-returns-error-34018-in-xcode-8-in-ios-10-simulator
                    // NOTE: code was not copy/pasted! That was iOS sample

                    sb.AppendLine("SecKeyChain.Add returned : " + eCode);
                    sb.AppendLine("1. Add Keychain Access Groups to the Entitlements file.");
                    sb.AppendLine("2. Turn on the Keychain Sharing switch in the Capabilities section in the app.");
                }

                string msg = sb.ToString();

                throw new ExceptionForUser(new Exception(msg));
            }
        }
        //------------------------------------------------------------------------------
        public bool Load(string settingName, SettingBaseAttribute attr, out object value)
        {
            if (!KeyChainUtils.Contains(settingName, m_serviceName, m_synchronizable))
            {
                InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                         "KeyChainSerializer.Load - no such setting",
                                                         settingName);

                value = null;
                return(false);
            }

            string        stringValue;
            SecStatusCode eCode = KeyChainUtils.GetPasswordForUsername(
                settingName,
                m_serviceName,
                out stringValue,
                m_synchronizable);

            if (eCode != SecStatusCode.Success || stringValue == null)
            {
                Advexp.LogLevel ll = Advexp.LogLevel.None;

                if (eCode == SecStatusCode.ItemNotFound)
                {
                    ll = LogLevel.Info;
                }
                else
                {
                    ll = LogLevel.Error;
                }

                InternalConfiguration.PlatformHelper.Log(ll,
                                                         "KeyChainSerializer.Load - error",
                                                         String.Format("Setting is {0}. Error code is {1}",
                                                                       settingName,
                                                                       eCode));
                value = null;
                return(false);
            }

            // in this case simplified object will be corrected in the SettingsSerializer.cs
            value = stringValue;

            InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                     "KeyChainSerializer.Load - success",
                                                     settingName);

            return(true);
        }
        //------------------------------------------------------------------------------
        public bool Contains(string settingName, SettingBaseAttribute attr)
        {
            bool contains = KeyChainUtils.Contains(
                settingName,
                m_serviceName,
                m_synchronizable);

            if (contains)
            {
                InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                         "KeyChainSerializer.Contains - setting exists",
                                                         settingName);
            }
            else
            {
                InternalConfiguration.PlatformHelper.Log(LogLevel.Info,
                                                         "KeyChainSerializer.Contains - no such setting",
                                                         settingName);
            }

            return(contains);
        }