/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.DefaultGroupId;
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().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());
        }

        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 DefaultGroupId(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);
    }
}
