/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/
 */
package org.phenotips.data.push.internal;

import org.phenotips.components.ComponentManagerRegistry;
import org.phenotips.configuration.RecordConfiguration;
import org.phenotips.configuration.RecordConfigurationManager;
import org.phenotips.data.push.PushServerConfigurationResponse;
import org.phenotips.data.shareprotocol.ShareProtocol;

import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;

import org.json.JSONArray;
import org.json.JSONObject;

public class DefaultPushServerConfigurationResponse extends DefaultPushServerResponse implements
    PushServerConfigurationResponse
{
    private static final String PATIENT_LABEL = "patient";

    DefaultPushServerConfigurationResponse(JSONObject serverResponse)
    {
        super(serverResponse);
    }

    protected Set<String> getSetFromJSONList(String key)
    {
        JSONArray stringList = this.response.optJSONArray(key);
        if (stringList == null) {
            return null;
        }

        Set<String> result = new TreeSet<>(); // to make sure order is unchanged
        for (Object field : stringList) {
            result.add(field.toString());
        }

        return Collections.unmodifiableSet(result);
    }

    @Override
    public Set<String> getRemoteUserGroups()
    {
        return getSetFromJSONList(ShareProtocol.SERVER_JSON_GETINFO_KEY_NAME_USERGROUPS);
    }

    @Override
    public Set<String> getRemoteAcceptedPatientFields()
    {
        return getRemoteAcceptedPatientFields(null);
    }

    @Override
    public Set<String> getRemoteAcceptedPatientFields(String groupName)
    {
        return getSetFromJSONList(ShareProtocol.SERVER_JSON_GETINFO_KEY_NAME_ACCEPTEDFIELDS);
    }

    @Override
    public Set<String> getPushableFields()
    {
        return getPushableFields(null);
    }

    @Override
    public Set<String> getPushableFields(String groupName)
    {
        try {
            Set<String> remoteAcceptedFields = getRemoteAcceptedPatientFields(groupName);

            if (remoteAcceptedFields == null) {
                return Collections.emptySet();
            }

            RecordConfigurationManager configurationManager =
                ComponentManagerRegistry.getContextComponentManager().getInstance(RecordConfigurationManager.class);

            RecordConfiguration patientConfig = configurationManager.getConfiguration(PATIENT_LABEL);

            Set<String> commonFields = new TreeSet<>(patientConfig.getEnabledFieldNames());

            // From the non-PII fields available, keep only those that are also enabled on the remote server
            commonFields.retainAll(remoteAcceptedFields);
            return commonFields;
        } catch (Exception ex) {
            return Collections.emptySet();
        }
    }

    @Override
    public boolean remoteUpdatesEnabled()
    {
        return hasKeySetToTrue(ShareProtocol.SERVER_JSON_GETINFO_KEY_NAME_UPDATESENABLED);
    }

    @Override
    public String getRemoteUserToken()
    {
        return valueOrNull(ShareProtocol.SERVER_JSON_GETINFO_KEY_NAME_USERTOKEN);
    }

    @Override
    public JSONArray getConsents()
    {
        return this.response.optJSONArray(ShareProtocol.SERVER_JSON_GETINFO_KEY_NAME_CONSENTS);
    }
}

@@ -2384,38 +2384,85 @@
 )%0A    %7B%0A        
-return
+Set%3CString%3E remoteAcceptedPatientFields =%0A           
  getSetFromJSONL
@@ -2521,24 +2521,1045 @@
 TEDFIELDS);%0A
+        String serverProtocolVersion = getServerProtocolVersion();%0A        // if genes are enabled for push, manually add variants to the list of enabled fields to generate push dialog%0A        // when pushing from the new instance where pushing genes and variants are enabled to push separately%0A        // to the older version where they are still grouped together%0A        if (remoteAcceptedPatientFields != null && !remoteAcceptedPatientFields.contains(%22variants%22)%0A            && ShareProtocol.INCOMPATIBILITIES_IN_OLD_PROTOCOL_VERSIONS.containsKey(serverProtocolVersion)%0A            && ShareProtocol.INCOMPATIBILITIES_IN_OLD_PROTOCOL_VERSIONS.get(serverProtocolVersion).contains(%0A                ShareProtocol.GENE_STATUS_INCOMPAT)%0A            && remoteAcceptedPatientFields.contains(%22genes%22)) %7B%0A            Set%3CString%3E result = new TreeSet%3C%3E(remoteAcceptedPatientFields);%0A            result.add(%22variants%22);%0A            return Collections.unmodifiableSet(result);%0A        %7D%0A        return remoteAcceptedPatientFields;%0A
     %7D%0A%0A    @

Add ability to consent/push/export genes and variants separately Manually add variants to the list of enabled filelds from remote server to generate variants chechbox option in push dialog, if genes are enabled when pushing from new protocol instance where genes and variants can be pushed separately to the old protocol instance where they are grouped together