/// <summary>
        /// Create a new credentials role.
        /// </summary>
        /// <param name="CountryCode">ISO-3166 alpha-2 country code of the country this party is operating in.</param>
        /// <param name="PartyId">CPO, eMSP (or other role) ID of this party (following the ISO-15118 standard).</param>
        /// <param name="Role">The type of the role.</param>
        /// <param name="BusinessDetails">Business details of this party.</param>
        /// <param name="AllowDowngrades">(Dis-)allow PUTting of object having an earlier 'LastUpdated'-timestamp then already existing objects.</param>
        public CredentialsRole(CountryCode CountryCode,
                               Party_Id PartyId,
                               Roles Role,
                               BusinessDetails BusinessDetails,
                               Boolean?AllowDowngrades = true)
        {
            if (CountryCode.IsNullOrEmpty)
            {
                throw new ArgumentNullException(nameof(CountryCode), "The given CountryCode must not be null or empty!");
            }

            if (PartyId.IsNullOrEmpty)
            {
                throw new ArgumentNullException(nameof(PartyId), "The given PartyId must not be null or empty!");
            }

            if (BusinessDetails is null)
            {
                throw new ArgumentNullException(nameof(BusinessDetails), "The given business details must not be null!");
            }


            this.CountryCode     = CountryCode;
            this.PartyId         = PartyId;
            this.Role            = Role;
            this.BusinessDetails = BusinessDetails;
            this.AllowDowngrades = AllowDowngrades;
        }
        public RemoteParty(CountryCode CountryCode,
                           Party_Id PartyId,
                           Roles Role,
                           BusinessDetails BusinessDetails,

                           IEnumerable <AccessInfo2> AccessInfos,
                           IEnumerable <RemoteAccessInfo> RemoteAccessInfos,

                           PartyStatus Status   = PartyStatus.ENABLED,
                           DateTime?LastUpdated = null)

        {
            this.Id = RemoteParty_Id.Parse(
                String.Concat(CountryCode.ToString(),
                              "-",
                              PartyId.ToString(),
                              "_",
                              Role.ToString()));

            this.CountryCode     = CountryCode;
            this.PartyId         = PartyId;
            this.Role            = Role;
            this.BusinessDetails = BusinessDetails;
            this.Status          = Status;
            this.LastUpdated     = LastUpdated ?? DateTime.UtcNow;

            this._AccessInfo        = AccessInfos.IsNeitherNullNorEmpty() ? new List <AccessInfo2>     (AccessInfos)       : new List <AccessInfo2>();
            this._RemoteAccessInfos = RemoteAccessInfos.IsNeitherNullNorEmpty() ? new List <RemoteAccessInfo>(RemoteAccessInfos) : new List <RemoteAccessInfo>();

            CalcSHA256Hash();
        }
        public RemoteParty(CountryCode CountryCode,
                           Party_Id PartyId,
                           Roles Role,
                           BusinessDetails BusinessDetails,

                           AccessToken RemoteAccessToken,
                           URL RemoteVersionsURL,
                           IEnumerable <Version_Id> RemoteVersionIds = null,
                           Version_Id?SelectedVersionId = null,

                           RemoteAccessStatus?RemoteStatus = RemoteAccessStatus.ONLINE,
                           PartyStatus Status = PartyStatus.ENABLED,

                           DateTime?LastUpdated = null)

            : this(CountryCode,
                   PartyId,
                   Role,
                   BusinessDetails,
                   null,
                   new RemoteAccessInfo[] {
            new RemoteAccessInfo(
                RemoteAccessToken,
                RemoteVersionsURL,
                RemoteVersionIds,
                SelectedVersionId,
                RemoteStatus
                )
        },
                   Status,
                   LastUpdated)

        {
        }
        public RemoteParty(CountryCode CountryCode,
                           Party_Id PartyId,
                           Roles Role,
                           BusinessDetails BusinessDetails,

                           AccessToken AccessToken,
                           AccessStatus AccessStatus = AccessStatus.ALLOWED,
                           PartyStatus Status        = PartyStatus.ENABLED,

                           DateTime?LastUpdated = null)

            : this(CountryCode,
                   PartyId,
                   Role,
                   BusinessDetails,
                   new AccessInfo2[] {
            new AccessInfo2(
                AccessToken,
                AccessStatus
                )
        },
                   null,
                   Status,
                   LastUpdated)

        {
        }
        /// <summary>
        /// Return a JSON representation of this object.
        /// </summary>
        /// <param name="Embedded">Whether this data is embedded into another data structure.</param>
        /// <param name="CustomRemotePartySerializer">A delegate to serialize custom remote party JSON objects.</param>
        /// <param name="CustomBusinessDetailsSerializer">A delegate to serialize custom business details JSON objects.</param>
        /// <param name="IncludeCryptoHash">Include the crypto hash value of this object.</param>
        public JObject ToJSON(Boolean Embedded,
                              CustomJObjectSerializerDelegate <RemoteParty> CustomRemotePartySerializer         = null,
                              CustomJObjectSerializerDelegate <BusinessDetails> CustomBusinessDetailsSerializer = null,
                              Boolean IncludeCryptoHash = false)
        {
            var JSON = JSONObject.Create(

                Id.ToJSON("@id"),

                Embedded
                               ? new JProperty("@context", DefaultJSONLDContext.ToString())
                               : null,

                new JProperty("countryCode", CountryCode.ToString()),
                new JProperty("partyId", PartyId.ToString()),
                new JProperty("role", Role.ToString()),
                new JProperty("partyStatus", Status.ToString()),

                BusinessDetails != null
                               ? new JProperty("businessDetails", BusinessDetails.ToJSON(CustomBusinessDetailsSerializer))
                               : null,

                _AccessInfo.SafeAny()
                               ? new JProperty("accessInfos", new JArray(_AccessInfo.SafeSelect(accessInfo => accessInfo.ToJSON())))
                               : null,

                _RemoteAccessInfos.SafeAny()
                               ? new JProperty("remoteAccessInfos", new JArray(_RemoteAccessInfos.SafeSelect(remoteAccessInfo => remoteAccessInfo.ToJSON())))
                               : null,

                new JProperty("last_updated", LastUpdated.ToIso8601()),

                IncludeCryptoHash
                               ? new JProperty("sha256Hash", SHA256Hash)
                               : null

                );

            return(CustomRemotePartySerializer != null
                       ? CustomRemotePartySerializer(this, JSON)
                       : JSON);
        }
        /// <summary>
        /// Return a JSON representation of this object.
        /// </summary>
        /// <param name="CustomCredentialsRoleSerializer">A delegate to serialize custom credentials roles JSON objects.</param>
        /// <param name="CustomBusinessDetailsSerializer">A delegate to serialize custom business details JSON objects.</param>
        public JObject ToJSON(CustomJObjectSerializerDelegate <CredentialsRole> CustomCredentialsRoleSerializer = null,
                              CustomJObjectSerializerDelegate <BusinessDetails> CustomBusinessDetailsSerializer = null)
        {
            var JSON = JSONObject.Create(

                new JProperty("country_code", CountryCode.ToString()),
                new JProperty("party_id", PartyId.ToString()),
                new JProperty("role", Role.ToString()),
                new JProperty("business_details", BusinessDetails.ToJSON(CustomBusinessDetailsSerializer))

                //AllowDowngrades.HasValue
                //    ? new JProperty("allow_downgrades",  AllowDowngrades.Value)
                //    : null

                );

            return(CustomCredentialsRoleSerializer != null
                       ? CustomCredentialsRoleSerializer(this, JSON)
                       : JSON);
        }