class ClientProcessor {

    public Boolean processField(JSONObject fieldJson, JSONObject event, JSONObject client) {

        try {
            if (fieldJson == null || fieldJson.length() == 0) {
                return false;
            }

            // keep checking if the event data matches the values expected by each rule, break the
            // moment the rule fails
            String dataSegment = null;
            String fieldName = fieldJson.has("field") ? fieldJson.getString("field") : null;
            String fieldValue =
                    fieldJson.has("field_value") ? fieldJson.getString("field_value") : null;
            String responseKey = null;

            if (fieldName != null && fieldName.contains(".")) {
                String fieldNameArray[] = fieldName.split("\\.");
                dataSegment = fieldNameArray[0];
                fieldName = fieldNameArray[1];
                String concept = fieldJson.has("concept") ? fieldJson.getString("concept") : null;

                if (concept != null) {
                    fieldValue = concept;
                    responseKey = VALUES_KEY;
                }
            }

            JSONArray createsCase =
                    fieldJson.has("creates_case") ? fieldJson.getJSONArray("creates_case") : null;
            JSONArray closesCase =
                    fieldJson.has("closes_case") ? fieldJson.getJSONArray("closes_case") : null;

            // some fields are in the main doc e.g event_type so fetch them from the main doc
            if (dataSegment != null && !dataSegment.isEmpty()) {

                JSONArray responseValue =
                        fieldJson.has(responseKey) ? fieldJson.getJSONArray(responseKey) : null;
                List<String> responseValues = getValues(responseValue);

                if (event.has(dataSegment)) {
                    JSONArray jsonDataSegment = event.getJSONArray(dataSegment);

                    // Iterate in the segment e.g obs segment
                    for (int j = 0; j < jsonDataSegment.length(); j++) {
                        JSONObject segmentJsonObject = jsonDataSegment.getJSONObject(j);
                        // let's discuss this further, to get the real value in the doc we've to
                        // use the keys 'fieldcode' and 'value'
                        String docSegmentFieldValue =
                                segmentJsonObject.has(fieldName) ? segmentJsonObject.get(fieldName)
                                        .toString() : "";
                        List<String> docSegmentResponseValues =
                                segmentJsonObject.has(responseKey) ? getValues(
                                        segmentJsonObject.get(responseKey)) : null;

                        if (docSegmentFieldValue.equalsIgnoreCase(fieldValue) && (!Collections
                                .disjoint(responseValues, docSegmentResponseValues))) {
                            // this is the event obs we're interested in put it in the respective
                            // bucket specified by type variable
                            processCaseModel(event, client, createsCase);
                            closeCase(client, closesCase);
                        }

                    }
                }

            } else {
                //fetch from the main doc
                String docSegmentFieldValue =
                        event.has(fieldName) ? event.get(fieldName).toString() : "";

                if (docSegmentFieldValue.equalsIgnoreCase(fieldValue)) {
                    processCaseModel(event, client, createsCase);
                    closeCase(client, closesCase);
                }

            }

            return true;
        } catch (Exception e) {
            Timber.e(e);

            return null;
        }
    }

    public  ClientProcessor(Context context);

}