/*
 * Copyright 2015-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.codec.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.util.HexString;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.group.DefaultGroup;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Group JSON codec.
 */
public final class GroupCodec extends JsonCodec<Group> {
    private final Logger log = getLogger(getClass());

    // JSON field names
    private static final String ID = "id";
    private static final String STATE = "state";
    private static final String LIFE = "life";
    private static final String PACKETS = "packets";
    private static final String BYTES = "bytes";
    private static final String REFERENCE_COUNT = "referenceCount";
    private static final String TYPE = "type";
    private static final String GROUP_ID = "groupId";
    private static final String DEVICE_ID = "deviceId";
    private static final String APP_ID = "appId";
    private static final String APP_COOKIE = "appCookie";
    private static final String GIVEN_GROUP_ID = "givenGroupId";
    private static final String BUCKETS = "buckets";
    private static final String MISSING_MEMBER_MESSAGE =
            " member is required in Group";
    public static final String REST_APP_ID = "org.onosproject.rest";

    @Override
    public ObjectNode encode(Group group, CodecContext context) {
        checkNotNull(group, "Group cannot be null");
        ObjectNode result = context.mapper().createObjectNode()
                .put(ID, group.id().id().toString())
                .put(STATE, group.state().toString())
                .put(LIFE, group.life())
                .put(PACKETS, group.packets())
                .put(BYTES, group.bytes())
                .put(REFERENCE_COUNT, group.referenceCount())
                .put(TYPE, group.type().toString())
                .put(DEVICE_ID, group.deviceId().toString());

        if (group.appId() != null) {
            result.put(APP_ID, group.appId().name());
        }

        if (group.appCookie() != null) {
            result.put(APP_COOKIE, group.appCookie().toString());
        }

        if (group.givenGroupId() != null) {
            result.put(GIVEN_GROUP_ID, group.givenGroupId().toString());
        }

        ArrayNode buckets = context.mapper().createArrayNode();
        group.buckets().buckets().forEach(bucket -> {
            ObjectNode bucketJson = context.codec(GroupBucket.class).encode(bucket, context);
            buckets.add(bucketJson);
        });
        result.set(BUCKETS, buckets);
        return result;
    }

    @Override
    public Group decode(ObjectNode json, CodecContext context) {
        if (json == null || !json.isObject()) {
            return null;
        }

        final JsonCodec<GroupBucket> groupBucketCodec = context.codec(GroupBucket.class);
        CoreService coreService = context.getService(CoreService.class);

        // parse group id
        int groupIdInt = nullIsIllegal(json.get(GROUP_ID),
                GROUP_ID + MISSING_MEMBER_MESSAGE).asInt();
        GroupId groupId = new GroupId(groupIdInt);

        // parse group key (appCookie)
        String groupKeyStr = nullIsIllegal(json.get(APP_COOKIE),
                APP_COOKIE + MISSING_MEMBER_MESSAGE).asText();
        if (!groupKeyStr.startsWith("0x")) {
            throw new IllegalArgumentException("APP_COOKIE must be a hex string starts with 0x");
        }
        GroupKey groupKey = new DefaultGroupKey(HexString.fromHexString(
                groupKeyStr.split("0x")[1], ""));

        // parse device id
        DeviceId deviceId = DeviceId.deviceId(nullIsIllegal(json.get(DEVICE_ID),
                DEVICE_ID + MISSING_MEMBER_MESSAGE).asText());

        // application id
        ApplicationId appId = coreService.registerApplication(REST_APP_ID);

        // parse group type
        String type = nullIsIllegal(json.get(TYPE),
                TYPE + MISSING_MEMBER_MESSAGE).asText();
        GroupDescription.Type groupType = null;

        switch (type) {
            case "SELECT":
                groupType = Group.Type.SELECT;
                break;
            case "INDIRECT":
                groupType = Group.Type.INDIRECT;
                break;
            case "ALL":
                groupType = Group.Type.ALL;
                break;
            case "FAILOVER":
                groupType = Group.Type.FAILOVER;
                break;
            default:
                nullIsIllegal(groupType, "The requested group type " + type + " is not valid");
        }

        // parse group buckets

        GroupBuckets buckets = null;
        List<GroupBucket> groupBucketList = new ArrayList<>();
        JsonNode bucketsJson = json.get(BUCKETS);
        checkNotNull(bucketsJson);
        if (bucketsJson != null) {
            IntStream.range(0, bucketsJson.size())
                    .forEach(i -> {
                        ObjectNode bucketJson = get(bucketsJson, i);
                        bucketJson.put("type", type);
                        groupBucketList.add(groupBucketCodec.decode(bucketJson, context));
                    });
            buckets = new GroupBuckets(groupBucketList);
        }

        GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
                groupType, buckets, groupKey, groupIdInt, appId);

        return new DefaultGroup(groupId, groupDescription);
    }
}
