/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

package stdx.net.http

import std.net.StreamingSocket
import stdx.log.Logger

public interface ProtocolServiceFactory {
    /*
     * @param protocol the version of the protocol, such as HTTP1_1, HTTP2_0
     * @return the instance of the ProtocolService
     */
    func create(protocol: Protocol, socket: StreamingSocket): ProtocolService
}

class ProtocolServiceFactoryImpl <: ProtocolServiceFactory {
    public func create(protocol: Protocol, socket: StreamingSocket): ProtocolService {
        return match (protocol) {
            case HTTP1_1 | HTTP1_0 | UnknownProtocol("") => HttpServer1(socket)
            case HTTP2_0 => HttpServer2(socket)
            case _ => throw HttpException("Protocol unknown.")
        }
    }
}

public abstract class ProtocolService {
    var _server: ?Server = None

    protected open mut prop server: Server {
        get() {
            _server ?? throw HttpException("Server instance not set yet.")
        }
        set(v) {
            _server = v
        }
    }

    /*
     * HttpRequestDistributor
     */
    protected prop distributor: HttpRequestDistributor {
        get() {
            server.distributor
        }
    }

    /*
     * Logger
     */
    protected prop logger: Logger {
        get() {
            server.logger
        }
    }

    /*
     * http settings
     * Read the entire request timeout.
     */
    protected prop readTimeout: Duration {
        get() {
            server.readTimeout
        }
    }

    /*
     * Write response timeout.
     */
    protected prop writeTimeout: Duration {
        get() {
            server.writeTimeout
        }
    }

    /*
     * Read header timeout.
     */
    protected prop readHeaderTimeout: Duration {
        get() {
            server.readHeaderTimeout
        }
    }

    /*
     * Http keep-alive timeout.
     */
    protected prop httpKeepAliveTimeout: Duration {
        get() {
            server.httpKeepAliveTimeout
        }
    }

    /*
     * Max size of headers per request.
     */
    protected prop maxRequestHeaderSize: Int64 {
        get() {
            server.maxRequestHeaderSize
        }
    }

    /*
     * Max size of body per request.
     */
    protected prop maxRequestBodySize: Int64 {
        get() {
            server.maxRequestBodySize
        }
    }

    /*
     * Handle the request from client.
     *
     * @param socket the StreamingSocket.
     */
    protected func serve(): Unit

    /*
     * Close ProtocolService gracefully.
     */
    protected open func closeGracefully(): Unit {}

    /*
     * Close ProtocolService forcibly.
     */
    protected open func close(): Unit {}
}