/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.shenyu.admin.model.entity;

import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.admin.model.dto.TagDTO;
import org.apache.shenyu.common.utils.UUIDUtils;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Optional;

public final class TagDO extends BaseDO {

    private static final long serialVersionUID = -3968123108441095604L;

    /**
     * name.
     */
    private String tagName;

    /**
     * tagDesc.
     */
    private String tagDesc;

    /**
     * parentTagId.
     */
    private String parentTagId;

    /**
     * ext.
     */
    private String ext;

    /**
     * getName.
     *
     * @return name
     */
    public String getTagName() {
        return tagName;
    }

    /**
     * set name.
     *
     * @param name name
     */
    public void setName(final String name) {
        this.tagName = name;
    }

    /**
     * getTagDesc.
     *
     * @return tagDesc
     */
    public String getTagDesc() {
        return tagDesc;
    }

    /**
     * setTagDesc.
     *
     * @param tagDesc tagDesc
     */
    public void setTagDesc(final String tagDesc) {
        this.tagDesc = tagDesc;
    }

    /**
     * getParentId.
     *
     * @return parentTagId
     */
    public String getParentTagId() {
        return parentTagId;
    }

    /**
     * setParentId.
     *
     * @param parentTagId parentId
     */
    public void setParentTagId(final String parentTagId) {
        this.parentTagId = parentTagId;
    }

    /**
     * getExt.
     *
     * @return ext
     */
    public String getExt() {
        return ext;
    }

    /**
     * setExt.
     *
     * @param ext ext
     */
    public void setExt(final String ext) {
        this.ext = ext;
    }

    /**
     * builder.
     *
     * @return TagDO.TagDOBuilder
     */
    public static TagDO.TagDOBuilder builder() {
        return new TagDO.TagDOBuilder();
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (Objects.isNull(o) || getClass() != o.getClass()) {
            return false;
        }
        if (!super.equals(o)) {
            return false;
        }
        TagDO tagDO = (TagDO) o;
        return Objects.equals(tagName, tagDO.tagName)
                && Objects.equals(tagDesc, tagDO.tagDesc)
                && Objects.equals(ext, tagDO.ext)
                && Objects.equals(parentTagId, tagDO.parentTagId);
    }

    /**
     * build tagDO.
     *
     * @param tagDTO {@linkplain TagDTO}
     * @return {@linkplain TagDO}
     */
    public static TagDO buildTagDO(final TagDTO tagDTO) {
        return Optional.ofNullable(tagDTO).map(item -> {
            Timestamp currentTime = new Timestamp(System.currentTimeMillis());
            TagDO tagDO = TagDO.builder()
                    .parentTagId(tagDTO.getParentTagId())
                    .tagDesc(tagDTO.getTagDesc())
                    .tagName(tagDTO.getTagName())
                    .dateUpdated(currentTime)
                    .build();
            if (StringUtils.isEmpty(item.getId())) {
                tagDO.setId(UUIDUtils.getInstance().generateShortUuid());
            } else {
                tagDO.setId(item.getId());
            }
            if (Objects.isNull(tagDO.getDateCreated())) {
                tagDO.setDateCreated(currentTime);
            }
            return tagDO;
        }).orElse(null);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), tagName, tagDesc, ext, parentTagId);
    }

    public static final class TagDOBuilder {

        private String id;

        private String tagName;

        private String tagDesc;

        private String parentTagId;

        private String ext;

        private Timestamp dateCreated;

        private Timestamp dateUpdated;

        private TagDOBuilder() {
        }

        /**
         * id.
         *
         * @param id the id.
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder id(final String id) {
            this.id = id;
            return this;
        }

        /**
         * dateCreated.
         *
         * @param dateCreated the dateCreated.
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder dateCreated(final Timestamp dateCreated) {
            this.dateCreated = dateCreated;
            return this;
        }

        /**
         * dateUpdated.
         *
         * @param dateUpdated the dateUpdated.
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder dateUpdated(final Timestamp dateUpdated) {
            this.dateUpdated = dateUpdated;
            return this;
        }

        /**
         * tagDesc.
         *
         * @param tagDesc tagDesc.
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder tagDesc(final String tagDesc) {
            this.tagDesc = tagDesc;
            return this;
        }

        /**
         * ext.
         *
         * @param ext ext.
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder ext(final String ext) {
            this.ext = ext;
            return this;
        }

        /**
         * parentTagId.
         *
         * @param parentTagId parentTagId.
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder parentTagId(final String parentTagId) {
            this.parentTagId = parentTagId;
            return this;
        }

        /**
         * name.
         *
         * @param tagName name
         * @return TagDOBuilder.
         */
        public TagDO.TagDOBuilder tagName(final String tagName) {
            this.tagName = tagName;
            return this;
        }

        /**
         * build.
         *
         * @return TagDO
         */
        public TagDO build() {
            TagDO tagDO = new TagDO();
            tagDO.setTagDesc(tagDesc);
            tagDO.setParentTagId(parentTagId);
            tagDO.setName(tagName);
            tagDO.setId(id);
            tagDO.setExt(ext);
            tagDO.setDateCreated(dateCreated);
            tagDO.setDateUpdated(dateUpdated);
            return tagDO;
        }
    }

    public static class TagExt implements Serializable {

        /**
         * id.
         */
        private String id;

        /**
         * desc.
         */
        private String desc;

        /**
         * name.
         */
        private String tagName;

        /**
         * parent.
         */
        private TagExt parent;

        /**
         * Last updated document time.
         */
        private Long refreshTime;

        /**
         * The md5 value of the swagger document for the application.
         */
        private String apiDocMd5;

        private String docLock;

        /**
         * get id.
         *
         * @return id
         */
        public String getId() {
            return id;
        }

        /**
         * set id.
         *
         * @param id id
         */
        public void setId(final String id) {
            this.id = id;
        }

        /**
         * get desc.
         *
         * @return get desc
         */
        public String getDesc() {
            return desc;
        }

        /**
         * set desc.
         *
         * @param desc desc
         */
        public void setDesc(final String desc) {
            this.desc = desc;
        }

        /**
         * get name.
         *
         * @return tagName tagName
         */
        public String getName() {
            return tagName;
        }

        /**
         * set name.
         *
         * @param tagName name
         */
        public void setName(final String tagName) {
            this.tagName = tagName;
        }

        /**
         * get parent.
         *
         * @return TagExt
         */
        public TagExt getParent() {
            return parent;
        }

        /**
         * set parent.
         *
         * @param parent parent
         */
        public void setParent(final TagExt parent) {
            this.parent = parent;
        }

        /**
         * get refreshTime.
         *
         * @return refreshTime
         */
        public Long getRefreshTime() {
            return refreshTime;
        }

        /**
         * set refreshTime.
         *
         * @param refreshTime refreshTime
         */
        public void setRefreshTime(final Long refreshTime) {
            this.refreshTime = refreshTime;
        }

        /**
         * get apiDoc md5.
         *
         * @return apiDocMd5
         */
        public String getApiDocMd5() {
            return apiDocMd5;
        }

        /**
         * set apiDoc md5.
         *
         * @param apiDocMd5 apiDocMd5
         */
        public void setApiDocMd5(final String apiDocMd5) {
            this.apiDocMd5 = apiDocMd5;
        }

        /**
         * get docLock.
         *
         * @return docLock
         */
        public String getDocLock() {
            return docLock;
        }

        /**
         * set docLock.
         *
         * @param docLock docLock
         */
        public void setDocLock(final String docLock) {
            this.docLock = docLock;
        }
    }

}
