package com.bocloud.ims.service.resource.azure;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.database.core.BasicDao;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.azure.blob.Blob;
import com.bocloud.ims.entity.resource.azure.blob.Container;
import com.bocloud.ims.entity.resource.azure.db.AzureDatabaseServer;
import com.bocloud.ims.entity.resource.azure.ddos.DdosProtectionPlan;
import com.bocloud.ims.entity.resource.azure.network.PublicIPAddress;
import com.bocloud.ims.entity.resource.azure.redis.CloudRedis;
import com.bocloud.ims.entity.resource.azure.slb.Slb;
import com.bocloud.ims.interfaces.resource.azure.ResourceLockService;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

/**
 * @author wangyu
 * @version 5.0.0-SNAPSHOT
 * @since 2021/3/16
 */
@Slf4j
@Service
public class ResourceLockServiceImpl implements ResourceLockService {

    @Autowired
    public LockFactory lockFactory;
    @Autowired
    public BasicDao basicDao;

    @Override
    public BocloudResult lock(Long id, String type, RequestContext context) {
        String path = type + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Class clazz = getClass(type);
            Assert.notNull(clazz, "no class found named " + type);
            Field locked = clazz.getDeclaredField("locked");
            Assert.notNull(locked, "not found field named locked");
            Object object = basicDao.loadEntity(clazz, id);
            Assert.notNull(object, "数据不存在");
            log.info("资源数据：{}", JSONObject.toJSONString(object));
            object.getClass().getDeclaredMethod("setLocked", Boolean.class).invoke(object, true);
            log.info("资源数据：{}", JSONObject.toJSONString(object));
            boolean flag = this.basicDao.updateEntity(object);
            return flag ? new BocloudResult(true, "资源锁定成功") : new BocloudResult(false, "资源锁定失败");
        } catch (Exception e) {
            log.error("Get error message:{}", e);
            return new BocloudResult(false, "资源锁定失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult release(Long id, String type, RequestContext context) {
        String path = type + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Class clazz = getClass(type);
            Assert.notNull(clazz, "no class found named " + type);
            Field locked = clazz.getDeclaredField("locked");
            Assert.notNull(locked, "not found field named locked");
            Object object = basicDao.loadEntity(clazz, id);
            object.getClass().getDeclaredMethod("setLocked", Boolean.class).invoke(object, false);
            boolean flag = this.basicDao.updateEntity(object);
            return flag ? new BocloudResult(true, "资源解锁成功") : new BocloudResult(false, "资源解锁失败");
        } catch (Exception e) {
            log.error("Get error message:{}", e);
            return new BocloudResult(false, "资源解锁失败：" + e.getMessage());
        }
    }

    private Class getClass(String type) {
        if (Blob.class.getSimpleName().equalsIgnoreCase(type)) {
            return Blob.class;
        } else if (Container.class.getSimpleName().equalsIgnoreCase(type)) {
            return Container.class;
        } else if (DdosProtectionPlan.class.getSimpleName().equalsIgnoreCase(type)) {
            return DdosProtectionPlan.class;
        } else if (CloudServer.class.getSimpleName().equalsIgnoreCase(type)) {
            return CloudServer.class;
        } else if (Volume.class.getSimpleName().equalsIgnoreCase(type)) {
            return Volume.class;
        } else if (ResourceGroup.class.getSimpleName().equalsIgnoreCase(type)) {
            return ResourceGroup.class;
        } else if (Vpc.class.getSimpleName().equalsIgnoreCase(type)) {
            return Vpc.class;
        } else if (NetworkInterface.class.getSimpleName().equalsIgnoreCase(type)) {
            return NetworkInterface.class;
        } else if (PublicIPAddress.class.getSimpleName().equalsIgnoreCase(type)) {
            return PublicIPAddress.class;
        } else if (Slb.class.getSimpleName().equalsIgnoreCase(type)) {
            return Slb.class;
        } else if (SecurityGroup.class.getSimpleName().equalsIgnoreCase(type)) {
            return SecurityGroup.class;
        } else if (Keypair.class.getSimpleName().equalsIgnoreCase(type)) {
            return Keypair.class;
        } else if (AzureDatabaseServer.class.getSimpleName().equalsIgnoreCase(type)) {
            return AzureDatabaseServer.class;
        } else if (CloudRedis.class.getSimpleName().equalsIgnoreCase(type)) {
            return CloudRedis.class;
        } else {
            return null;
        }
    }
}
