/**
 * Copyright © 2016-2021 The Thingsboard Authors
 *
 * 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.thingsboard.server.transport.lwm2m.config;

import com.google.common.io.Resources;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URI;
import java.security.KeyStore;

@Slf4j
@Component
@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'")
public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {

    @Getter
    @Setter
    private LwM2mModelProvider modelProvider;

    @Getter
    @Value("${transport.lwm2m.timeout:}")
    private Long timeout;

    @Getter
    @Value("${transport.sessions.report_timeout}")
    private long sessionReportTimeout;

    @Getter
    @Value("${transport.lwm2m.recommended_ciphers:}")
    private boolean recommendedCiphers;

    @Getter
    @Value("${transport.lwm2m.recommended_supported_groups:}")
    private boolean recommendedSupportedGroups;

    @Getter
    @Value("${transport.lwm2m.downlink_pool_size:}")
    private int downlinkPoolSize;

    @Getter
    @Value("${transport.lwm2m.uplink_pool_size:}")
    private int uplinkPoolSize;

    @Getter
    @Value("${transport.lwm2m.ota_pool_size:}")
    private int otaPoolSize;

    @Getter
    @Value("${transport.lwm2m.clean_period_in_sec:}")
    private int cleanPeriodInSec;

    @Getter
    @Value("${transport.lwm2m.security.key_store_type:}")
    private String keyStoreType;

    @Getter
    @Value("${transport.lwm2m.security.key_store:}")
    private String keyStorePathFile;

    @Getter
    @Setter
    private KeyStore keyStoreValue;

    @Getter
    @Value("${transport.lwm2m.security.key_store_password:}")
    private String keyStorePassword;

    @Getter
    @Value("${transport.lwm2m.security.root_alias:}")
    private String rootCertificateAlias;

    @Getter
    @Value("${transport.lwm2m.security.enable_gen_new_key_psk_rpk:}")
    private Boolean enableGenNewKeyPskRpk;

    @Getter
    @Value("${transport.lwm2m.server.id:}")
    private Integer id;

    @Getter
    @Value("${transport.lwm2m.server.bind_address:}")
    private String host;

    @Getter
    @Value("${transport.lwm2m.server.bind_port:}")
    private Integer port;

    @Getter
    @Value("${transport.lwm2m.server.security.bind_address:}")
    private String secureHost;

    @Getter
    @Value("${transport.lwm2m.server.security.bind_port:}")
    private Integer securePort;

    @Getter
    @Value("${transport.lwm2m.server.security.public_x:}")
    private String publicX;

    @Getter
    @Value("${transport.lwm2m.server.security.public_y:}")
    private String publicY;

    @Getter
    @Value("${transport.lwm2m.server.security.private_encoded:}")
    private String privateEncoded;

    @Getter
    @Value("${transport.lwm2m.server.security.alias:}")
    private String certificateAlias;

    @Getter
    @Value("${transport.lwm2m.log_max_length:}")
    private int logMaxLength;


    @PostConstruct
    public void init() {
        URI uri = null;
        try {
            uri = Resources.getResource(keyStorePathFile).toURI();
            log.info("URI: {}", uri);
            File keyStoreFile = new File(uri);
            InputStream inKeyStore = new FileInputStream(keyStoreFile);
            keyStoreValue = KeyStore.getInstance(keyStoreType);
            keyStoreValue.load(inKeyStore, keyStorePassword == null ? null : keyStorePassword.toCharArray());
        } catch (Exception e) {
            log.info("Unable to lookup LwM2M keystore. Reason: {}, {}" , uri, e.getMessage());
        }
    }
}

@@ -2558,24 +2558,24 @@
 keyStore
-Path
 File
+Path
 ;%0A%0A    @
@@ -4062,148 +4062,572 @@
     
-uri = Resources.getResource(keyStorePathFile).toURI();%0A            log.info(%22URI: %7B%7D%22, uri);%0A            File keyStoreFile = new File(uri);%0A
+InputStream keyStoreInputStream;%0A            File keyStoreFile = new File(keyStoreFilePath);%0A            if (keyStoreFile.exists()) %7B%0A                log.info(%22Reading key store from file %7B%7D%22, keyStoreFilePath);%0A                keyStoreInputStream = new FileInputStream(keyStoreFile);%0A            %7D else %7B%0A                InputStream classPathStream = this.getClass().getClassLoader().getResourceAsStream(keyStoreFilePath);%0A                if (classPathStream != null) %7B%0A                    log.info(%22Reading key store from class path %7B%7D%22, keyStoreFilePath);%0A     
     
@@ -4626,32 +4626,43 @@
                 
+   keyStore
 InputStream inKe
@@ -4657,26 +4657,255 @@
 tStream 
-inKeyStore
+= classPathStream;%0A                %7D else %7B%0A                    uri = Resources.getResource(keyStoreFilePath).toURI();%0A                    log.info(%22Reading key store from URI %7B%7D%22, keyStoreFilePath);%0A                    keyStoreInputStream
  = new F
@@ -4915,39 +4915,72 @@
 InputStream(
-keyStoreFile
+new File(uri)
 );%0A
+                %7D%0A            %7D%0A
             
@@ -5066,18 +5066,27 @@
 oad(
-inK
+k
 eyStore
+InputStream
 , ke
@@ -5252,17 +5252,16 @@
  %7B%7D, %7B%7D%22
- 
 , uri, e
@@ -5292,10 +5292,11 @@
 %7D%0A    %7D%0A
+%0A
 %7D%0A

Correct KeyStore Lookup