/*
 * 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.dubbo.config.bootstrap.builders;

import org.apache.dubbo.config.ProtocolConfig;

import java.util.Map;

/**
 * This is a builder for build {@link ProtocolConfig}.
 *
 * @since 2.7
 */
public class ProtocolBuilder extends AbstractBuilder<ProtocolConfig, ProtocolBuilder> {
    /**
     * Protocol name
     */
    private String name;

    /**
     * Service ip address (when there are multiple network cards available)
     */
    private String host;

    /**
     * Service port
     */
    private Integer port;

    /**
     * Context path
     */
    private String contextpath;

    /**
     * Thread pool
     */
    private String threadpool;

    /**
     * Thread pool core thread size
     */
    private Integer corethreads;

    /**
     * Thread pool size (fixed size)
     */
    private Integer threads;

    /**
     * IO thread pool size (fixed size)
     */
    private Integer iothreads;

    /**
     * Thread pool's queue length
     */
    private Integer queues;

    /**
     * Max acceptable connections
     */
    private Integer accepts;

    /**
     * Protocol codec
     */
    private String codec;

    /**
     * Serialization
     */
    private String serialization;

    /**
     * Charset
     */
    private String charset;

    /**
     * Payload max length
     */
    private Integer payload;

    /**
     * Buffer size
     */
    private Integer buffer;

    /**
     * Heartbeat interval
     */
    private Integer heartbeat;

    /**
     * Access log
     */
    private String accesslog;

    /**
     * Transporter
     */
    private String transporter;

    /**
     * How information is exchanged
     */
    private String exchanger;

    /**
     * Thread dispatch mode
     */
    private String dispatcher;

    /**
     * Networker
     */
    private String networker;

    /**
     * Sever impl
     */
    private String server;

    /**
     * Client impl
     */
    private String client;

    /**
     * Supported telnet commands, separated with comma.
     */
    private String telnet;

    /**
     * Command line prompt
     */
    private String prompt;

    /**
     * Status check
     */
    private String status;

    /**
     * Whether to register
     */
    private Boolean register;

    /**
     * whether it is a persistent connection
     */
    // TODO add this to provider config
    private Boolean keepAlive;

    // TODO add this to provider config
    private String optimizer;

    /**
     * The extension
     */
    private String extension;

    /**
     * The customized parameters
     */
    private Map<String, String> parameters;

    private Boolean sslEnabled;

    /*
     * Extra Protocol for this service, using Port Unification Server
     */
    private String extProtocol;

    /**
     * If it's default
     */
    private Boolean isDefault;

    public static ProtocolBuilder newBuilder() {
        return new ProtocolBuilder();
    }

    public ProtocolBuilder id(String id) {
        return super.id(id);
    }

    public ProtocolBuilder name(String name) {
        this.name = name;
        return getThis();
    }

    public ProtocolBuilder host(String host) {
        this.host = host;
        return getThis();
    }

    public ProtocolBuilder port(Integer port) {
        this.port = port;
        return getThis();
    }

    public ProtocolBuilder contextpath(String contextpath) {
        this.contextpath = contextpath;
        return getThis();
    }

    /**
     * @param path
     * @return ProtocolBuilder
     * @see ProtocolBuilder#contextpath(String)
     */
    @Deprecated
    public ProtocolBuilder path(String path) {
        this.contextpath = path;
        return getThis();
    }

    public ProtocolBuilder threadpool(String threadpool) {
        this.threadpool = threadpool;
        return getThis();
    }

    public ProtocolBuilder corethreads(Integer corethreads) {
        this.corethreads = corethreads;
        return getThis();
    }

    public ProtocolBuilder threads(Integer threads) {
        this.threads = threads;
        return getThis();
    }

    public ProtocolBuilder iothreads(Integer iothreads) {
        this.iothreads = iothreads;
        return getThis();
    }

    public ProtocolBuilder queues(Integer queues) {
        this.queues = queues;
        return getThis();
    }

    public ProtocolBuilder accepts(Integer accepts) {
        this.accepts = accepts;
        return getThis();
    }

    public ProtocolBuilder codec(String codec) {
        this.codec = codec;
        return getThis();
    }

    public ProtocolBuilder serialization(String serialization) {
        this.serialization = serialization;
        return getThis();
    }

    public ProtocolBuilder charset(String charset) {
        this.charset = charset;
        return getThis();
    }

    public ProtocolBuilder payload(Integer payload) {
        this.payload = payload;
        return getThis();
    }

    public ProtocolBuilder buffer(Integer buffer) {
        this.buffer = buffer;
        return getThis();
    }

    public ProtocolBuilder heartbeat(Integer heartbeat) {
        this.heartbeat = heartbeat;
        return getThis();
    }

    public ProtocolBuilder accesslog(String accesslog) {
        this.accesslog = accesslog;
        return getThis();
    }

    public ProtocolBuilder transporter(String transporter) {
        this.transporter = transporter;
        return getThis();
    }

    public ProtocolBuilder exchanger(String exchanger) {
        this.exchanger = exchanger;
        return getThis();
    }

    public ProtocolBuilder dispatcher(String dispatcher) {
        this.dispatcher = dispatcher;
        return getThis();
    }

    /**
     * @param dispather
     * @return ProtocolBuilder
     * @see ProtocolBuilder#dispatcher(String)
     */
    @Deprecated
    public ProtocolBuilder dispather(String dispather) {
        this.dispatcher = dispather;
        return getThis();
    }

    public ProtocolBuilder networker(String networker) {
        this.networker = networker;
        return getThis();
    }

    public ProtocolBuilder server(String server) {
        this.server = server;
        return getThis();
    }

    public ProtocolBuilder client(String client) {
        this.client = client;
        return getThis();
    }

    public ProtocolBuilder telnet(String telnet) {
        this.telnet = telnet;
        return getThis();
    }

    public ProtocolBuilder prompt(String prompt) {
        this.prompt = prompt;
        return getThis();
    }

    public ProtocolBuilder status(String status) {
        this.status = status;
        return getThis();
    }

    public ProtocolBuilder register(Boolean register) {
        this.register = register;
        return getThis();
    }

    public ProtocolBuilder keepAlive(Boolean keepAlive) {
        this.keepAlive = keepAlive;
        return getThis();
    }

    public ProtocolBuilder optimizer(String optimizer) {
        this.optimizer = optimizer;
        return getThis();
    }

    public ProtocolBuilder extension(String extension) {
        this.extension = extension;
        return getThis();
    }

    public ProtocolBuilder appendParameter(String key, String value) {
        this.parameters = appendParameter(parameters, key, value);
        return getThis();
    }

    public ProtocolBuilder appendParameters(Map<String, String> appendParameters) {
        this.parameters = appendParameters(parameters, appendParameters);
        return getThis();
    }

    public ProtocolBuilder isSslEnabled(Boolean sslEnabled) {
        this.sslEnabled = sslEnabled;
        return getThis();
    }

    public ProtocolBuilder extProtocol(String extProtocol) {
        this.extProtocol = extProtocol;
        return getThis();
    }

    public ProtocolBuilder isDefault(Boolean isDefault) {
        this.isDefault = isDefault;
        return getThis();
    }

    @Override
    public ProtocolConfig build() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        super.build(protocolConfig);

        protocolConfig.setAccepts(accepts);
        protocolConfig.setAccesslog(accesslog);
        protocolConfig.setBuffer(buffer);
        protocolConfig.setCharset(charset);
        protocolConfig.setClient(client);
        protocolConfig.setCodec(codec);
        protocolConfig.setContextpath(contextpath);
        protocolConfig.setCorethreads(corethreads);
        protocolConfig.setDefault(isDefault);
        protocolConfig.setDispatcher(dispatcher);
        protocolConfig.setExchanger(exchanger);
        protocolConfig.setExtension(extension);
        protocolConfig.setHeartbeat(heartbeat);
        protocolConfig.setHost(host);
        protocolConfig.setIothreads(iothreads);
        protocolConfig.setKeepAlive(keepAlive);
        protocolConfig.setName(name);
        protocolConfig.setNetworker(networker);
        protocolConfig.setOptimizer(optimizer);
        protocolConfig.setParameters(parameters);
        protocolConfig.setPayload(payload);
        protocolConfig.setPort(port);
        protocolConfig.setPrompt(prompt);
        protocolConfig.setQueues(queues);
        protocolConfig.setRegister(register);
        protocolConfig.setSerialization(serialization);
        protocolConfig.setServer(server);
        protocolConfig.setStatus(status);
        protocolConfig.setTelnet(telnet);
        protocolConfig.setThreadpool(threadpool);
        protocolConfig.setThreads(threads);
        protocolConfig.setTransporter(transporter);
        protocolConfig.setSslEnabled(sslEnabled);
        protocolConfig.setExtProtocol(extProtocol);

        return protocolConfig;
    }

    @Override
    protected ProtocolBuilder getThis() {
        return this;
    }
}
