package tests

import (
	"testing"
	"time"

	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/handler/cachehandler"
	"github.com/pingcap/dbaas/billing2/handler/centralhandler"

	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/constant"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/model/marketing/discount"
	"github.com/pingcap/dbaas/billing2/model/marketing/unit_filter"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/pingcap/dbaas/billing2/utils/timeutils"
	"github.com/shopspring/decimal"
	"github.com/stretchr/testify/suite"
)

var discountModel = &discount.Model{}
var unitFilterModel = &unit_filter.Model{}

type MockCentralHandlerImpl struct {
	centralhandler.CentralHandler
}

func (*MockCentralHandlerImpl) GetTenant(tenantID uint) (*forms.Tenant, error) {
	return &forms.Tenant{
		TenantID:                  tenantID,
		ThirdPartyAccountCode:     "rasdcsa",
		ThirdPartyAccountProvider: constant.AwsAccountProvider,
		Status:                    centralhandler.TenantStatusActive,
	}, nil
}

func (*MockCentralHandlerImpl) GetProjectInfo(projectID uint) (*forms.Project, error) {
	return &forms.Project{
		ID:   projectID,
		Name: "project",
	}, nil
}

type DiscountTestSuite struct {
	tests.BillingTestSuite
}

func TestDiscountTestSuite(t *testing.T) {
	suite.Run(t, new(DiscountTestSuite))
}

func (s *DiscountTestSuite) SetupTest() {
	s.BillingTestSuite.SetupTest()
	assert := s.Assert()
	config.Get().Set(config.EnableCache, true)
	cachehandler.InitWithLocal()
	generalUnitFilter, err := unitFilterModel.CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "General", Description: "General"},
		General:        true,
	})
	assert.NoError(err)
	config.Get().Set(config.GeneralCreditTypeID, generalUnitFilter.FilterID)
	centralhandler.SetCentralHandler(&MockCentralHandlerImpl{})
}

func (s *DiscountTestSuite) TearDownTest() {
	s.BillingTestSuite.SetupTest()
	config.Get().Set(config.EnableCache, false)
}

func (s *DiscountTestSuite) TestSetDiscount() {
	tenantID := uint(1)
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	assert := s.Assert()
	concurrency := 10
	billingConfigID := uint(1)
	channels := make([]chan error, concurrency)
	costFunc := func(ch chan error) {
		_, err := discountModel.SetDiscount(&forms.ChangeBindedDiscountInput{
			BindedDiscount:        decimal.NewFromInt(3),
			ChangerTenantID:       tenantID,
			BindedBillingConfigID: &billingConfigID,
		})
		assert.NoError(err)
		close(ch)
	}
	for i := 0; i != concurrency; i++ {
		channels[i] = make(chan error)
		go costFunc(channels[i])
	}
	for i := 0; i != concurrency; i++ {
		select {
		case <-channels[i]:
		case <-time.After(2 * time.Second):
			panic("unexpected timeout")
		}
	}
	ds, err := discountModel.ListTenantDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(ds, 1)
	assert.NotZero(ds[0].Version)
}

func (s *DiscountTestSuite) TestDiscountCRUD() {
	var err error
	tenantID := uint(1)
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	billingConfigID := uint(1)

	assert := s.Assert()
	timeutils.SetMockNow(datainit.BillingDate)
	now := timeutils.GetNow()
	tenantDiscount := decimal.RequireFromString("0.77")
	req := &forms.Discount{
		Value:                 tenantDiscount,
		StartedAt:             now,
		ExpiredAt:             now.AddDate(1, 0, 0),
		UnitFilters:           []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
		BindedBillingConfigID: &billingConfigID,
	}
	td, err := discountModel.CreateDiscount(tenantID, req)
	assert.NoError(err)
	assert.Equal(req.Value, td.Value)
	assert.Equal(req.StartedAt, td.StartedAt)
	assert.Equal(req.ExpiredAt, td.ExpiredAt)
	assert.Equal(constant.DiscountStatus_Valid, td.Status)
	assert.Equal(constant.DiscountActive, td.Active)
	assert.Equal(req.UnitFilters[0].FilterID, td.UnitFiltersInternal[0].FilterID)

	//globalDiscount := decimal.RequireFromString("0.88")
	//req.Value = globalDiscount
	//gd, err := discountModel.CreateDiscount(0, req)
	//assert.NoError(err)
	//assert.Equal(req.Value, gd.Value)
	//assert.Equal(constant.DiscountStatus_Valid, gd.Status)
	//assert.Zero(gd.TenantID)

	tenantDiscounts, err := discountModel.ListTenantDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(tenantDiscounts, 1)
	assert.Equal(td, tenantDiscounts[0])

	//globalDiscounts, err := discountModel.ListGlobalDiscounts()
	//assert.NoError(err)
	//assert.Len(globalDiscounts, 1)
	//assert.Equal(gd, globalDiscounts[0])

	consoleViewDiscount, err := discountModel.ListDiscountsConsoleView(tenantID, 1)
	assert.NoError(err)
	assert.Len(consoleViewDiscount, 1)

	effectiveDiscount, err := discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount, 1)

	//err = discountModel.DeleteDiscount(0, gd.DiscountID)
	//assert.NoError(err)
	//
	//globalDiscounts, err = discountModel.ListGlobalDiscounts()
	//assert.NoError(err)
	//assert.Equal(constant.DiscountStatus_Reclaimed, globalDiscounts[0].Status)

	effectiveDiscount, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount, 1)
	timeutils.SetMockNow(now.Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	_, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	effectiveDiscount, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount, 1)

	timeutils.SetMockNow(now.AddDate(1, 1, 0))
	tenantDiscounts, err = discountModel.ListTenantDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Equal(constant.DiscountStatus_Expired, tenantDiscounts[0].Status)

	effectiveDiscount, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount, 1)
	timeutils.SetMockNow(timeutils.GetNow().Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	_, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	effectiveDiscount, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount, 0)

	//timeutils.SetMockNow(now)
	//noDiscount := decimal.RequireFromString("1")
	//req.Value = noDiscount
	//nd, err := discountModel.CreateDiscount(0, req)
	//assert.NoError(err)
	//assert.Equal(noDiscount, nd.Value)
	//assert.Equal(constant.DiscountStatus_Valid, nd.Status)
	//assert.Zero(gd.TenantID)

	consoleViewDiscount, err = discountModel.ListDiscountsConsoleView(tenantID, 1)
	assert.NoError(err)
	assert.Len(consoleViewDiscount, 1)
}

func (s *DiscountTestSuite) TestValidateDiscountReq() {
	var err error
	assert := s.Assert()
	timeutils.SetMockNow(datainit.BillingDate)
	now := timeutils.GetNow()
	tenantDiscount := decimal.RequireFromString("0.77")
	req := &forms.Discount{
		Value:       tenantDiscount,
		StartedAt:   now,
		ExpiredAt:   now.AddDate(-1, 0, 0),
		UnitFilters: []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
	}
	err = discount.ValidateDiscountReq(req)
	assert.Error(err)
	req.StartedAt = now.AddDate(-1, 0, 0)
	req.ExpiredAt = now.AddDate(0, -1, 0)
	err = discount.ValidateDiscountReq(req)
	assert.Error(err)

	req.StartedAt = now
	req.ExpiredAt = now.AddDate(1, 0, 0)
	req.Value = decimal.NewFromInt(-1000)
	err = discount.ValidateDiscountReq(req)
	assert.Error(err)

	req.Value = tenantDiscount
	err = discount.ValidateDiscountReq(req)
	assert.NoError(err)
}

func (s *DiscountTestSuite) TestDiscountConsoleView() {
	var err error
	tenantID := uint(1)
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	billingConfigID := uint(1)

	assert := s.Assert()
	timeutils.SetMockNow(datainit.BillingDate)
	start := timeutils.GetNow()
	d := decimal.RequireFromString("0.77")
	req := &forms.Discount{
		Value:                 d,
		StartedAt:             start.AddDate(0, 1, 0),
		ExpiredAt:             start.AddDate(0, 2, 0),
		UnitFilters:           []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
		BindedBillingConfigID: &billingConfigID,
	}
	//assert.NoError(err)
	//_, err = discountModel.CreateDiscount(tenantID, req)
	assert.NoError(err)
	req.ExpiredAt = start.AddDate(0, 3, 0)
	//gd2, err := discountModel.CreateDiscount(0, req)
	//assert.NoError(err)
	_, err = discountModel.CreateDiscount(tenantID, req)
	assert.NoError(err)
	req.StartedAt = start.AddDate(0, 3, 0)
	req.ExpiredAt = start.AddDate(0, 4, 0)
	//gd3, err := discountModel.CreateDiscount(0, req)
	//assert.NoError(err)
	req.StartedAt = start.AddDate(0, 2, 0)
	_, err = discountModel.CreateDiscount(tenantID, req)
	assert.NoError(err)

	tenantDiscounts, err := discountModel.ListTenantDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(tenantDiscounts, 2)
	//globalDiscounts, err := discountModel.ListGlobalDiscounts()
	//assert.NoError(err)
	//assert.Len(globalDiscounts, 3)
	effectiveDiscounts, err := discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscounts, 2)
	consoleViewDiscounts, err := discountModel.ListDiscountsConsoleView(tenantID, 1)
	assert.NoError(err)
	assert.Len(consoleViewDiscounts, 2)

	timeutils.SetMockNow(start.AddDate(0, 1, 0))
	//gd1, err = discountModel.GetDiscount(0, gd1.DiscountID)
	assert.NoError(err)
	effectiveDiscounts, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscounts, 2)
	consoleViewDiscounts, err = discountModel.ListDiscountsConsoleView(tenantID, 1)
	assert.NoError(err)
	assert.Len(consoleViewDiscounts, 2)
	//assert.Contains(consoleViewDiscounts, gd1)

	timeutils.SetMockNow(start.AddDate(0, 2, 0).Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	rows, err := discountModel.InactiveTimeoutDiscount()
	assert.Equal(int64(0), rows)
	//gd2, err = discountModel.GetDiscount(0, gd2.DiscountID)
	assert.NoError(err)
	effectiveDiscounts, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscounts, 2)
	consoleViewDiscounts, err = discountModel.ListDiscountsConsoleView(tenantID, 1)
	assert.NoError(err)
	assert.Len(consoleViewDiscounts, 2)
	//assert.Contains(consoleViewDiscounts, gd2)

	timeutils.SetMockNow(start.AddDate(0, 3, 0).Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.Equal(int64(1), rows)
	//gd3, err = discountModel.GetDiscount(0, gd3.DiscountID)
	assert.NoError(err)
	effectiveDiscounts, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscounts, 1)
	consoleViewDiscounts, err = discountModel.ListDiscountsConsoleView(tenantID, 1)
	assert.NoError(err)
	assert.Len(consoleViewDiscounts, 2)
	//assert.Contains(consoleViewDiscounts, gd3)
}

func (s *DiscountTestSuite) TestDiscountCache() {
	config.Get().Set(config.EnableCache, true)
	defer func() {
		config.Get().Set(config.EnableCache, false)
	}()
	var err error
	tenantID := uint(1)
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	billingConfigID := uint(1)

	assert := s.Assert()
	timeutils.SetMockNow(datainit.BillingDate)
	now := timeutils.GetNow()
	tenantDiscount := decimal.RequireFromString("0.77")
	req := &forms.Discount{
		Value:                 tenantDiscount,
		StartedAt:             now,
		ExpiredAt:             now.AddDate(1, 0, 0),
		UnitFilters:           []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
		BindedBillingConfigID: &billingConfigID,
	}
	td, err := discountModel.CreateDiscount(tenantID, req)
	assert.NoError(err)
	assert.Equal(req.Value, td.Value)
	assert.Equal(req.StartedAt, td.StartedAt)
	assert.Equal(req.ExpiredAt, td.ExpiredAt)
	assert.Equal(constant.DiscountStatus_Valid, td.Status)
	assert.Equal(td.Active, constant.DiscountActive)
	assert.Equal(req.UnitFilters[0].FilterID, td.UnitFiltersInternal[0].FilterID)

	globalDiscount := decimal.RequireFromString("0.88")
	req.Value = globalDiscount
	//gd, err := discountModel.CreateDiscount(0, req)
	//assert.NoError(err)
	//assert.Equal(req.Value, gd.Value)
	//assert.Equal(constant.DiscountStatus_Valid, gd.Status)
	//assert.Zero(gd.TenantID)

	effectiveDiscount1, err := discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount1, 1)

	effectiveDiscount2, err := discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(effectiveDiscount2, 1)

	assert.Equal(effectiveDiscount1, effectiveDiscount2)
}

func (suite *DiscountTestSuite) TestInactiveTimeoutDiscount() {
	var err error
	assert := suite.Assert()
	timeutils.SetMockNow(datainit.BillingDate)
	tenantDiscount := decimal.RequireFromString("0.08")
	tenantID := uint(1)
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	billingConfigID := uint(1)

	exDate1 := datainit.BillingDate.AddDate(1, 0, 0)
	exDate2 := datainit.BillingDate.AddDate(0, 1, 0)
	req := forms.Discount{
		Value:                 tenantDiscount,
		StartedAt:             datainit.BillingDate,
		ExpiredAt:             exDate1,
		UnitFilters:           []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
		BindedBillingConfigID: &billingConfigID,
	}
	d1, err := discountModel.CreateDiscount(tenantID, &req)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d1.Active)
	err = discountModel.DeleteDiscount(tenantID, d1.DiscountID)
	assert.NoError(err)
	d1, err = discountModel.GetDiscount(tenantID, d1.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountStatus_Reclaimed, d1.Status)
	assert.Equal(constant.DiscountActive, d1.Active)
	d2, err := discountModel.CreateDiscount(tenantID, &req)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d2.Active)
	req2 := req
	req2.ExpiredAt = exDate2
	d3, err := discountModel.CreateDiscount(tenantID, &req2)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d3.Active)
	//d4, err := discountModel.CreateDiscount(0, &req)
	//assert.NoError(err)
	//assert.Equal(constant.DiscountActive, d4.Active)
	infos, err := discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(infos, 3)
	rows, err := discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Zero(rows)
	timeutils.SetMockNow(datainit.BillingDate.Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	infos, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(infos, 2)
	d1, err = discountModel.GetDiscount(tenantID, d1.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d1.Active)

	timeutils.SetMockNow(exDate2)
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Equal(int64(0), rows)
	infos, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(infos, 2)
	timeutils.SetMockNow(exDate2.Add(time.Hour * config.Get().GetDuration(config.BindedPackageInactiveDelayHour)))
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	infos, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(infos, 1)
	d3, err = discountModel.GetDiscount(tenantID, d3.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d3.Active)
	timeutils.SetMockNow(exDate1)
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Equal(int64(0), rows)
	infos, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(infos, 1)
	timeutils.SetMockNow(exDate1.Add(time.Hour * config.Get().GetDuration(config.BindedPackageInactiveDelayHour)))
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	infos, err = discountModel.ListEffectiveDiscounts(tenantID, 1)
	assert.NoError(err)
	assert.Len(infos, 0)
	d2, err = discountModel.GetDiscount(tenantID, d2.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d2.Active)
	//d4, err = discountModel.GetDiscount(0, d4.DiscountID)
	//assert.NoError(err)
	//assert.Equal(constant.DiscountInactive, d4.Active)

	timeutils.SetMockNow(datainit.BillingDate)
	tenantID2 := uint(2)
	req = forms.Discount{
		Value:                 tenantDiscount,
		StartedAt:             datainit.BillingDate,
		ExpiredAt:             exDate1,
		UnitFilters:           []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
		BindedBillingConfigID: &billingConfigID,
	}
	d5, err := discountModel.CreateDiscount(tenantID, &req)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d5.Active)
	d6, err := discountModel.CreateDiscount(tenantID2, &req)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d6.Active)
	d7, err := discountModel.CreateDiscount(tenantID, &req2)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d7.Active)
	d8, err := discountModel.CreateDiscount(tenantID2, &req)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d8.Active)
	//d9, err := discountModel.CreateDiscount(0, &req)
	//assert.NoError(err)
	//assert.Equal(constant.DiscountActive, d9.Active)

	err = discountModel.DeleteDiscount(d5.TenantID, d5.DiscountID)
	assert.NoError(err)
	err = discountModel.DeleteDiscount(d8.TenantID, d8.DiscountID)
	assert.NoError(err)
	timeutils.SetMockNow(datainit.BillingDate.Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	rows, err = discountModel.InactiveTimeoutDiscount(tenantID2)
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	d5, err = discountModel.GetDiscount(d5.TenantID, d5.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d5.Active)
	d8, err = discountModel.GetDiscount(d8.TenantID, d8.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d8.Active)
	rows, err = discountModel.InactiveTimeoutDiscount(tenantID)
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	d5, err = discountModel.GetDiscount(d5.TenantID, d5.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d5.Active)

	timeutils.SetMockNow(exDate1)
	rows, err = discountModel.InactiveTimeoutDiscount(tenantID2)
	assert.NoError(err)
	assert.Equal(int64(0), rows)
	timeutils.SetMockNow(exDate1.Add(time.Hour * config.Get().GetDuration(config.DiscountInactiveDelayHour)))
	rows, err = discountModel.InactiveTimeoutDiscount(tenantID2)
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	d6, err = discountModel.GetDiscount(d6.TenantID, d6.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d6.Active)
	d7, err = discountModel.GetDiscount(d7.TenantID, d7.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountActive, d7.Active)
	//d9, err = discountModel.GetDiscount(d9.TenantID, d9.DiscountID)
	//assert.NoError(err)
	//assert.Equal(constant.DiscountActive, d9.Active)

	//rows, err = discountModel.InactiveTimeoutDiscount(0)
	//assert.NoError(err)
	//assert.Equal(int64(0), rows)
	//d9, err = discountModel.GetDiscount(d9.TenantID, d9.DiscountID)
	//assert.NoError(err)
	//assert.Equal(constant.DiscountInactive, d9.Active)
	rows, err = discountModel.InactiveTimeoutDiscount()
	assert.NoError(err)
	assert.Equal(int64(1), rows)
	d7, err = discountModel.GetDiscount(d7.TenantID, d7.DiscountID)
	assert.NoError(err)
	assert.Equal(constant.DiscountInactive, d7.Active)
}
