// 从相对路径 '../common/component' 导入名为 'VantComponent' 的模块，这里假设 'VantComponent' 是一个用于创建特定组件的函数，遵循着相应的组件构建规范或框架约定。
import { VantComponent } from '../common/component';

// 调用 'VantComponent' 函数来创建一个组件，传入一个配置对象，该对象用于定义组件的各种属性、数据、监听以及方法等相关信息，以此来定制组件的行为和功能。
VantComponent({
    // 'field' 属性设置为 true，这里可能暗示该组件与表单字段相关联，或许会参与表单相关的交互逻辑，比如在表单提交时的验证、取值等操作，具体功能依赖于所在框架的实现方式。
    field: true,
    // 'classes' 属性定义了一个外部可传入的类名列表，这里包含了 'icon-class'，意味着外部在使用这个组件时，可以通过传入这个类名来定制组件中与图标相关的样式，增强组件样式的可定制性。
    classes: ['icon-class'],
    // 'props' 属性用于定义组件可接收的外部属性（类似于其他框架中的 props 概念），是一个对象，对象中的每个键值对代表一个具体的外部属性及其相关配置，包括类型、默认值等信息。
    props: {
        // 'value' 属性，其值被限定为数字类型（`Number`），外部使用组件时需要传入符合数字格式的数据，该属性通常用于存储组件的一个数值相关的值，具体含义根据组件功能而定，可能是评分值之类的关键数据。
        value: Number,
        //'readonly' 属性，类型为布尔类型（`Boolean`），用于控制组件是否处于只读状态，外部传入 `true` 或 `false` 来决定用户是否能够对组件进行操作，例如在展示评分但不允许修改的场景下可以设置为 `true`。
        readonly: Boolean,
        // 'disabled' 属性，同样是布尔类型（`Boolean`），用于设置组件是否处于禁用状态，当设置为 `true` 时，用户通常不能与组件进行交互操作，常用于根据业务逻辑限制组件可用性的情况。
        disabled: Boolean,
        // 'allowHalf' 属性，布尔类型（`Boolean`），可能用于控制组件是否允许出现半分值之类的情况，比如评分组件中是否支持打半分，具体功能取决于组件的业务逻辑设计。
        allowHalf: Boolean,
        //'size' 属性，详细定义了它的类型为数字类型（`type: Number`），并且设置了默认值为 `20`，大概率用于控制组件中某个元素（可能是图标等）的尺寸大小，外部也可以传入其他数字来改变默认的尺寸设置。
        size: {
            type: Number,
            value: 20
        },
        // 'icon' 属性，限定接收的值类型为字符串类型（`String`），默认值为 `'star'`，很可能用于指定组件中表示某种状态（如选中状态）的图标名称，方便通过图标来展示组件的相关状态，外部可传入其他字符串来更换图标。
        icon: {
            type: String,
            value: 'star'
        },
        // 'voidIcon' 属性，也是字符串类型（`String`），默认值为 `'star-o'`，可能用于表示组件中与 'icon' 相对应的另一种状态（如未选中状态）的图标名称，同样可由外部传入不同字符串进行定制。
        voidIcon: {
            type: String,
            value: 'star-o'
        },
        // 'color' 属性，类型为字符串类型（`String`），默认值为 `'#ffd21e'`，通常用于设置组件中某个元素（比如选中状态图标）的颜色，外部可以传入符合颜色表示规范的字符串来改变默认颜色。
        color: {
            type: String,
            value: '#ffd21e'
        },
        // 'voidColor' 属性，同样是字符串类型（`String`），默认值为 `'#c7c7c7'`，大概率用于设置未选中状态相关元素的颜色，可通过外部传入字符串来进行颜色定制。
        voidColor: {
            type: String,
            value: '#c7c7c7'
        },
        // 'disabledColor' 属性，类型为字符串类型（`String`），默认值为 `'#bdbdbd'`，用于设定组件处于禁用状态时相关元素呈现的颜色，外部可传入合适字符串改变此颜色设置。
        disabledColor: {
            type: String,
            value: '#bdbdbd'
        },
        // 'count' 属性，其类型为数字类型（`Number`），默认值为 `5`，很可能用于表示组件中某种元素的数量，比如评分组件中星星图标的数量，外部可以传入不同数字来调整数量。
        count: {
            type: Number,
            value: 5
        }
    },
    // 'data' 属性用于定义组件内部的数据状态，这些数据可以在组件的各个方法中使用和修改，这里定义了 'innerValue' 并初始化为 `0`，可能用于在组件内部临时存储和处理一些与外部 'value' 属性相关的值，或者用于记录组件的中间状态等。
    data: {
        innerValue: 0
    },
    // 'watch' 属性用于定义对组件数据的监听逻辑，这里监听了 'value' 属性的变化，当 'value' 的值发生改变时，会执行对应的回调函数。
    watch: {
        value(value) {
            // 在 'value' 的新值与组件内部的 'innerValue' 不相等时，说明 'value' 属性发生了实际的变化，此时通过 'this.set' 方法（这里假设是所在框架用于更新组件数据的方法）更新 'innerValue' 的值，使其与 'value' 保持一致，确保组件内部状态与外部传入的属性值同步。
            if (value!== this.data.innerValue) {
                this.set({ innerValue: value });
            }
        }
    },
    //'methods' 属性用于定义组件内部可调用的方法，这些方法实现了组件的各种交互逻辑和业务功能，比如响应用户的操作等。
    methods: {
        // 定义名为 'onSelect' 的方法，该方法可能在用户进行选择操作（比如点击某个图标来选择评分等情况）时被触发，接收一个 'event' 参数，包含了触发事件时的相关信息。
        onSelect(event) {
            // 解构出组件内部的数据对象，方便后续访问组件的各个数据属性，例如判断组件是否处于禁用或只读状态等。
            const { data } = this;
            // 从触发事件的目标元素（`event.currentTarget`）的数据集（`dataset`）中获取名为'score' 的数据，这里的'score' 可能代表用户选择的某个分值相关的数据，具体含义取决于组件的业务逻辑设计。
            const { score } = event.currentTarget.dataset;
            // 判断组件当前既不处于禁用状态（`!data.disabled`）也不处于只读状态（`!data.readonly`），即用户可以进行操作的情况下，执行以下逻辑。
            if (!data.disabled &&!data.readonly) {
                // 通过 'this.set' 方法更新组件内部的 'innerValue' 属性为用户选择的分值加 `1`，这里加 `1` 的操作可能与组件具体的分值计算逻辑有关，比如索引从 `0` 开始但分值从 `1` 开始计数等情况。
                this.set({ innerValue: score + 1 });
                // 使用 '$emit' 方法（这里假设是所在框架用于触发自定义事件的机制）向外触发一个名为 'input' 的自定义事件，并将用户选择的分值加 `1` 作为参数传递出去，方便外部组件监听该事件获取用户选择的分值，常用于与表单等相关的双向数据绑定场景。
                this.$emit('input', score + 1);
                // 同样使用 '$emit' 方法向外触发一个名为 'change' 的自定义事件，也将用户选择的分值加 `1` 作为参数传递出去，外部可以监听该事件来执行相应的业务逻辑，比如更新页面其他部分显示的总分等情况。
                this.$emit('change', score + 1);
            }
        },
        // 定义名为 'onTouchMove' 的方法，该方法可能在用户触摸屏幕并移动手指（比如在移动端进行滑动操作）时被触发，接收 'event' 参数，包含触摸移动事件相关的信息。
        onTouchMove(event) {
            // 从触摸事件对象的第一个触摸点（`event.touches[0]`）中解构出 'clientX'（触摸点的横坐标，相对于浏览器窗口左上角的位置）和 'clientY'（触摸点的纵坐标）属性，方便后续判断触摸点所在的位置。
            const { clientX, clientY } = event.touches[0];
            // 调用组件内部的 'getRect' 方法（这里假设该方法用于获取指定选择器对应的元素的布局矩形信息，可能是基于所在框架提供的相关 API 实现），传入选择器 '.van-rate__icon' 并设置 `true` 表示获取所有匹配的元素，返回一个 `Promise`，在获取到元素信息后进行后续处理。
            this.getRect('.van-rate__icon', true).then((list) => {
                // 对获取到的元素列表（`list`）进行排序操作，排序规则是根据每个元素的右边界（`right`）减去左边界（`left`）的值来升序排列，这样可以方便后续按照从左到右的顺序查找触摸点所在的元素。
                const target = list
                    .sort(item => item.right - item.left)
                    // 使用 `find` 方法在排好序的元素列表中查找符合条件的元素，条件是触摸点的横坐标（`clientX`）在元素的左边界（`left`）和右边界（`right`）之间，并且纵坐标（`clientY`）在元素的上边界（`top`）和下边界（`bottom`）之间，找到的元素即为触摸点所在的目标元素。
                    .find(item => clientX >= item.left &&
                        clientX <= item.right &&
                        clientY >= item.top &&
                        clientY <= item.bottom);
                // 如果找到了目标元素（`target` 不为 `null`），则调用 'onSelect' 方法，模拟用户点击该目标元素的操作逻辑，传入一个经过处理的事件对象（将原事件对象和目标元素合并，模拟点击事件中目标元素的相关信息），以便执行相应的选择和事件触发逻辑。
                if (target!= null) {
                    this.onSelect(Object.assign({}, event, { currentTarget: target }));
                }
            });
        }
    }
});