/*
 * Copyright 2017-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.ui.topo;

import com.google.common.base.Strings;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Represents a "node location" on a UI layout.
 */
public final class LayoutLocation {
    private static final double ZERO_THRESHOLD = Double.MIN_VALUE * 2.0;
    private static final String COMMA = ",";
    private static final String TILDE = "~";
    private static final String EMPTY = "";

    private static final String E_BAD_COMPACT = "Badly formatted compact form: ";
    private static final String E_EMPTY_ID = "id must be non-empty";
    private static final String E_BAD_DOUBLE = "unparsable double";


    /**
     * Designates the type of location; either geographic or logical grid.
     */
    public enum Type {
        GEO, GRID;

        @Override
        public String toString() {
            return name().toLowerCase();
        }
    }

    private final String id;
    private final double latOrY;
    private final double longOrX;
    private final Type locType;

    private LayoutLocation(String id, Type locType, double latOrY, double longOrX) {
        this.id = id;
        this.latOrY = latOrY;
        this.longOrX = longOrX;
        this.locType = locType;
    }

    private boolean doubleIsZero(double value) {
        return value >= -ZERO_THRESHOLD && value <= ZERO_THRESHOLD;
    }

    /**
     * Returns true if the coordinates indicate the origin (0, 0) of the
     * coordinate system; false otherwise.
     *
     * @return true if geo-coordinates are set; false otherwise
     */
    public boolean isOrigin() {
        return doubleIsZero(latOrY) && doubleIsZero(longOrX);
    }

    /**
     * Returns the identifier associated with this location.
     *
     * @return the identifier
     */
    public String id() {
        return id;
    }

    /**
     * Returns the location type (geo or grid), which indicates how the data
     * is to be interpreted.
     *
     * @return location type
     */
    public Type locType() {
        return locType;
    }

    /**
     * Returns the latitude (geo) or y-coord (grid) data value.
     *
     * @return geo latitude or grid y-coord
     */
    public double latOrY() {
        return latOrY;
    }

    /**
     * Returns the longitude (geo) or x-coord (grid) data value.
     *
     * @return geo longitude or grid x-coord
     */
    public double longOrX() {
        return longOrX;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("id", id)
                .add("loc-type", locType)
                .add("lat/Y", latOrY)
                .add("long/X", longOrX)
                .toString();
    }

    /**
     * Produces a compact string representation of this instance.
     *
     * @return compact string rep
     */
    public String toCompactListString() {
        return id + COMMA + locType + COMMA + latOrY + COMMA + longOrX;
    }

    /**
     * Produces a layout location instance from a compact string representation.
     *
     * @param s the compact string
     * @return a corresponding instance
     */
    public static LayoutLocation fromCompactString(String s) {
        String[] tokens = s.split(COMMA);
        if (tokens.length != 4) {
            throw new IllegalArgumentException(E_BAD_COMPACT + s);
        }
        String id = tokens[0];
        String type = tokens[1];
        String latY = tokens[2];
        String longX = tokens[3];

        if (Strings.isNullOrEmpty(id)) {
            throw new IllegalArgumentException(E_BAD_COMPACT + E_EMPTY_ID);
        }

        double latOrY;
        double longOrX;
        try {
            latOrY = Double.parseDouble(latY);
            longOrX = Double.parseDouble(longX);
        } catch (NumberFormatException nfe) {
            throw new IllegalArgumentException(E_BAD_COMPACT + E_BAD_DOUBLE);
        }

        return LayoutLocation.layoutLocation(id, type, latOrY, longOrX);
    }

    /**
     * Produces a compact encoding of a list of layout locations.
     *
     * @param locs array of layout location instances
     * @return string encoding
     */
    public static String toCompactListString(LayoutLocation... locs) {
        if (locs == null || locs.length == 0) {
            return EMPTY;
        }
        List<LayoutLocation> lls = Arrays.asList(locs);
        return toCompactListString(lls);
    }

    /**
     * Produces a compact encoding of a list of layout locations.
     *
     * @param locs list of layout location instances
     * @return string encoding
     */
    public static String toCompactListString(List<LayoutLocation> locs) {
        // note: locs may be empty
        if (locs == null || locs.isEmpty()) {
            return EMPTY;
        }

        StringBuilder sb = new StringBuilder();
        for (LayoutLocation ll : locs) {
            sb.append(ll.toCompactListString()).append(TILDE);
        }
        final int len = sb.length();
        sb.replace(len - 1, len, "");
        return sb.toString();
    }

    /**
     * Returns a list of layout locations from a compact string representation.
     *
     * @param compactList string representation
     * @return corresponding list of layout locations
     */
    public static List<LayoutLocation> fromCompactListString(String compactList) {
        List<LayoutLocation> locs = new ArrayList<>();
        if (!Strings.isNullOrEmpty(compactList)) {
            String[] items = compactList.split(TILDE);
            for (String s : items) {
                locs.add(fromCompactString(s));
            }
        }
        return locs;
    }


    /**
     * Creates an instance of a layout location.
     *
     * @param id      an identifier for the item at this location
     * @param locType the location type
     * @param latOrY  geo latitude / grid y-coord
     * @param longOrX geo longitude / grid x-coord
     * @return layout location instance
     */
    public static LayoutLocation layoutLocation(String id, Type locType,
                                                double latOrY, double longOrX) {
        checkNotNull(id, "must supply an identifier");
        checkNotNull(locType, "must declare location type");
        return new LayoutLocation(id, locType, latOrY, longOrX);
    }

    /**
     * Creates an instance of a layout location.
     *
     * @param id      an identifier for the item at this location
     * @param locType the location type ("geo" or "grid")
     * @param latOrY  geo latitude / grid y-coord
     * @param longOrX geo longitude / grid x-coord
     * @return layout location instance
     * @throws IllegalArgumentException if the type is not "geo" or "grid"
     */
    public static LayoutLocation layoutLocation(String id, String locType,
                                                double latOrY, double longOrX) {
        Type t = Type.valueOf(locType.toUpperCase());
        return new LayoutLocation(id, t, latOrY, longOrX);
    }
}
